Android - RecyclerView NullPointerException getItemCount?

时间:2016-08-02 07:47:27

标签: android android-recyclerview android-adapter

我有一个让我崩溃的recyclerView:

enter image description here

这是我的StartActivity:

public class StartActivity extends AppCompatActivity {

    TextView txtTest;
    private ProgressDialog pDialog;
    // These tags will be used to cancel the requests
    private String tag_json_obj = "jobj_req", tag_json_arry = "jarray_req";

    private RecyclerView.Adapter mAdapter;
    RecyclerView UserCode_Recycler;
    private LinearLayoutManager mLayoutManager;


    List<Marketing_Code> userCodeList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_start);
        txtTest = (TextView) findViewById(R.id.txtTest);
        UserCode_Recycler = (RecyclerView) findViewById(R.id.UserCode_Recycler);
        pDialog = new ProgressDialog(this);
        pDialog.setMessage("Loading...");
        pDialog.setCancelable(false);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        if (fab != null) {
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                            .setAction("Action", null).show();
                }
            });
        }

        makeJsonArryReq();

        userCodeList = new ArrayList<>();
        // create an Object for Adapter
        mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);
        // set the adapter object to the Recyclerview
        UserCode_Recycler.setAdapter(mAdapter);

        mAdapter.notifyDataSetChanged();


        UserCode_Recycler.setHasFixedSize(true);

        mLayoutManager = new LinearLayoutManager(this);
        // use a linear layout manager
        UserCode_Recycler.setLayoutManager(mLayoutManager);

    }

    private void showProgressDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    private void hideProgressDialog() {
        if (pDialog.isShowing())
            pDialog.hide();
    }


    /**
     * Making json array request
     */
    private void makeJsonArryReq() {
        showProgressDialog();
        JsonArrayRequest req = new JsonArrayRequest(Const.Marketing_List,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d("MYData", response.toString());
                        userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());
                       /* // create an Object for Adapter
                        mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);
                        // set the adapter object to the Recyclerview
                        Search_Recycler.setAdapter(mAdapter);
                        mAdapter.notifyDataSetChanged();
                        //txtTest.setText(response.toString());*/
                        mAdapter.notifyDataSetChanged();
                        hideProgressDialog();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d("Custom Log Error", "Error: " + error.getMessage());
                hideProgressDialog();
            }
        });

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(req, tag_json_arry);
        // Cancelling request
        // ApplicationController.getInstance().getRequestQueue().cancelAll(tag_json_arry);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

我的适配器:

public class UserCodeList_Adapter extends RecyclerView.Adapter<UserCodeList_Adapter.ViewHolder> {

    private List<Marketing_Code> ucList;
    public static Activity activity;
    public UserCodeList_Adapter(List<Marketing_Code> userCodeList, Activity activity) {
        this.ucList = userCodeList;
        this.activity = activity;
    }
    @Override
    public UserCodeList_Adapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // create a new view
        View itemLayoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.listmarketing_cardview, null);

        // create ViewHolder
        ViewHolder viewHolder = new ViewHolder(itemLayoutView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(UserCodeList_Adapter.ViewHolder viewHolder, int position) {
        String userCode =String.valueOf(ucList.get(position).getMarketCode());
        viewHolder.txtUserID.setText(userCode);
    }

    @Override
    public int getItemCount() {
        return ucList.size();
        //return ucList == null ? 0 : ucList.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        public TextView txtUserID;

        public Marketing_Code items;

        public ViewHolder(View itemLayoutView) {
            super(itemLayoutView);

            txtUserID = (TextView) itemLayoutView.findViewById(R.id.txtUserID);
            // Onclick event for the row to show the data in toast
            itemLayoutView.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                }
            });

        }

    }
}

4 个答案:

答案 0 :(得分:2)

您尚未初始化userCodeList

看到您的代码,您将适配器基于尚未初始化的列表。因此,当适配器尝试了解您的列表中有多少项时,它会抛出NullPointerException

将您的userCodeList声明更改为如下所示:

List<Marketing_Code> userCodeList = new ArrayList<>();

看到您更新的问题,您似乎将数据基于JSON响应。如果是这种情况,那么您目前正在做的事情几乎正确。

观察您稍微修改过的代码片段:

private void makeJsonArryReq() {
    showProgressDialog();
    JsonArrayRequest req = new JsonArrayRequest(Const.Marketing_List,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d("MYData", response.toString());
                    /* YOUR OLD CODE -> */ // userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());
                    /* HOW IT SHOULD'VE BEEN */ userCodeList.addAll(MarketingCode_JSONParser.parseFeed(response.toString()));
                    mAdapter.notifyDataSetChanged();
                    hideProgressDialog();
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d("Custom Log Error", "Error: " + error.getMessage());
            hideProgressDialog();
        }
    });

// ...

查看上面代码段的注释部分。这样做可以解决您的问题,并在屏幕上显示数据。

答案 1 :(得分:1)

处理此问题的两种方法:

  1. 在请求检查其大小

    之前,您需要检查列表是否为NULL
    public int getItemCount () {
        if(ucList == null)
            return 0;
        return ucList.size();
    }
    
  2. 或者,,这是推荐的解决此问题的方法,是在开始时将其初始化为空列表,或者确保在它被访问之前始终初始化它相关适配器。

    List<Marketing_Code> userCodeList = new ArrayList<>();

  3. 希望这有帮助。

答案 2 :(得分:0)

我认为您需要对列表使用replaceAll函数,而不是直接等同。 这里

 userCodeList = MarketingCode_JSONParser.parseFeed(response.toString());

尝试在初始化适配器之前检查userCodeList是否包含任何数据。

答案 3 :(得分:0)

请执行以下操作并尝试

   // create an Object for Adapter        
    userCodeList = new ArrayList<>();
    mAdapter = new UserCodeList_Adapter(userCodeList, StartActivity.this);