Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

notifyDataSetChanged not working on RecyclerView

I am getting data from server and then parsing it and storing it in a List. I am using this list for the RecyclerView's adapter. I am using Fragments.

I am using a Nexus 5 with KitKat. I am using support library for this. Will this make a difference?

Here is my code: (Using dummy data for the question)

Member Variables:

List<Business> mBusinesses = new ArrayList<Business>();  RecyclerView recyclerView; RecyclerView.LayoutManager mLayoutManager; BusinessAdapter mBusinessAdapter; 

My onCreateView():

@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,         Bundle savedInstanceState) {      // Getting data from server     getBusinessesDataFromServer();      View view = inflater.inflate(R.layout.fragment_business_list,             container, false);     recyclerView = (RecyclerView) view             .findViewById(R.id.business_recycler_view);     recyclerView.setHasFixedSize(true);      mLayoutManager = new LinearLayoutManager(getActivity());     recyclerView.setLayoutManager(mLayoutManager);      mBusinessAdapter = new BusinessAdapter(mBusinesses);     recyclerView.setAdapter(mBusinessAdapter);      return view; } 

After getting data from server, parseResponse() is called.

protected void parseResponse(JSONArray response, String url) {     // insert dummy data for demo      mBusinesses.clear();      Business business;      business = new Business();     business.setName("Google");     business.setDescription("Google HeadQuaters");     mBusinesses.add(business);      business = new Business();     business.setName("Yahoo");     business.setDescription("Yahoo HeadQuaters");     mBusinesses.add(business);      business = new Business();     business.setName("Microsoft");     business.setDescription("Microsoft HeadQuaters");     mBusinesses.add(business);      Log.d(Const.DEBUG, "Dummy Data Inserted\nBusinesses Length: "             + mBusinesses.size());      mBusinessAdapter = new BusinessAdapter(mBusinesses);     mBusinessAdapter.notifyDataSetChanged(); } 

My BusinessAdapter:

public class BusinessAdapter extends     RecyclerView.Adapter<BusinessAdapter.ViewHolder> {      private List<Business> mBusinesses = new ArrayList<Business>();      // Provide a reference to the type of views that you are using     // (custom viewholder)     public static class ViewHolder extends RecyclerView.ViewHolder {         public TextView mTextViewName;         public TextView mTextViewDescription;         public ImageView mImageViewLogo;          public ViewHolder(View v) {             super(v);             mTextViewName = (TextView) v                     .findViewById(R.id.textView_company_name);             mTextViewDescription = (TextView) v                     .findViewById(R.id.textView_company_description);             mImageViewLogo = (ImageView) v                     .findViewById(R.id.imageView_company_logo);         }     }      // Provide a suitable constructor (depends on the kind of dataset)     public BusinessAdapter(List<Business> myBusinesses) {          Log.d(Const.DEBUG, "BusinessAdapter -> constructor");          mBusinesses = myBusinesses;     }      // Create new views (invoked by the layout manager)     @Override     public BusinessAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,             int viewType) {          Log.d(Const.DEBUG, "BusinessAdapter -> onCreateViewHolder()");          // create a new view         View v = LayoutInflater.from(parent.getContext()).inflate(                 R.layout.item_business_list, parent, false);          ViewHolder vh = new ViewHolder(v);         return vh;     }      // Replace the contents of a view (invoked by the layout manager)     @Override     public void onBindViewHolder(ViewHolder holder, int position) {         // - get element from your dataset at this position         // - replace the contents of the view with that element          Log.d(Const.DEBUG, "BusinessAdapter -> onBindViewHolder()");          Business item = mBusinesses.get(position);         holder.mTextViewName.setText(item.getName());         holder.mTextViewDescription.setText(item.getDescription());         holder.mImageViewLogo.setImageResource(R.drawable.ic_launcher);      }      // Return the size of your dataset (invoked by the layout manager)     @Override     public int getItemCount() {          Log.d(Const.DEBUG, "BusinessAdapter -> getItemCount()");          if (mBusinesses != null) {             Log.d(Const.DEBUG, "mBusinesses Count: " + mBusinesses.size());             return mBusinesses.size();         }         return 0;     } } 

But I don't get the data displayed in the view. What am I doing wrong?

Here is my log,

07-14 21:15:35.669: D/xxx(2259): Dummy Data Inserted 07-14 21:15:35.669: D/xxx(2259): Businesses Length: 3 07-14 21:26:26.969: D/xxx(2732): BusinessAdapter -> constructor 

I don't get any logs after this. Shouldn't getItemCount() in adapter should be called again?

like image 848
Vamsi Challa Avatar asked Jul 14 '14 15:07

Vamsi Challa


People also ask

What does notifyDataSetChanged do in Recyclerview?

notifyDataSetChanged. Notify any registered observers that the data set has changed. There are two different classes of data change events, item changes and structural changes. Item changes are when a single item has its data updated but no positional changes have occurred.

How does notifyDataSetChanged work on Android?

Suppose your ListView displays some data stored in an ArrayList . After you change the contents of the ArrayList , you need to tell the list that the source of the data had changed and it needs to redraw itself to show the new data. So, that is where notifyDatasetChanged() comes in.

What happens when we call notifyDataSetChanged?

From the docs notifyDataSetChanged() : Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

What is the difference between onCreateViewHolder and onBindViewHolder?

When used, pass the child Class Object, and in onCreateViewHolder , use Reflection to create the child ViewHolder. When you get an onBindViewHolder, just pass it to the ViewHolder.


1 Answers

In your parseResponse() you are creating a new instance of the BusinessAdapter class, but you aren't actually using it anywhere, so your RecyclerView doesn't know the new instance exists.

You either need to:

  • Call recyclerView.setAdapter(mBusinessAdapter) again to update the RecyclerView's adapter reference to point to your new one
  • Or just remove mBusinessAdapter = new BusinessAdapter(mBusinesses); to continue using the existing adapter. Since you haven't changed the mBusinesses reference, the adapter will still use that array list and should update correctly when you call notifyDataSetChanged().
like image 73
Bryan Herbst Avatar answered Sep 24 '22 21:09

Bryan Herbst