Android - RecyclerView NullPointerException getItemCount?

馋奶兔 提交于 2019-12-13 17:18:13

问题


I have a recyclerView that it get me crash :

Here is my 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);
    }
}

And my adapter :

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) {
                }
            });

        }

    }
}

回答1:


You haven't initialized your userCodeList.

Seeing your code, you based your adapter to that list while it is not yet initialized. Consequently, when the adapter tried to learn how much item your list have it throws a NullPointerException.

Change your declaration of userCodeList to one like below:

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

Seeing your updated question, you seem to base your data from a JSON response. If that's the case, what you're currently doing is almost correct.

Observe this slightly modified snippet of your code:

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();
        }
    });

// ...

Look at the commented part of the above snippet. Doing so should solve your problem and make the data visible on screen.




回答2:


Two ways to handle this:

  1. You need to check if the list is NULL before requesting to check its size

    public int getItemCount () {
        if(ucList == null)
            return 0;
        return ucList.size();
    }
    
  2. Alternatively, and this is the recommended approach to this matter, is to initialise it to an empty list at the start or make sure that it is always initialised before it is accessed by the associated adapter.

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

Hope this helps.




回答3:


I think you need to use replaceAll function for the list ,instead of directly equating. Here

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

Try checking if userCodeList contains any data before initialzing the adapter.




回答4:


Please do the following and try

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


来源:https://stackoverflow.com/questions/38714629/android-recyclerview-nullpointerexception-getitemcount

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!