Jo Jo Roid Jo Jo Roid - 4 months ago 41
Android Question

Android - RecyclerView NullPointerException getItemCount?

I have a recyclerView that it get me crash :

enter image description here

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

}

}
}

Answer

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 do is almost correct.

Observe this snippet from 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.