Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView change data set

I want to implement search functionality for my RecyclerView. On text changed i want to change the data that are displayed with this widget. Maybe this question has been asked before or is simple, but I don't know how the change the data that is to be shown...

My RecyclerView is defined as follows:

     // 1. get a reference to recyclerView     mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);      // 2. set layoutManger     mRecyclerView.setLayoutManager(new LinearLayoutManager(this));     // 3. create an adapter     mAdapter = new ItemsAdapter(itemsData);     // 4. set adapter     mRecyclerView.setAdapter(mAdapter); 

And the data that I am showing is something like:

   ItemData itemsData[] = { new ItemData("Mary Richards"),         new ItemData("Tom Brown"),         new ItemData("Lucy London")           }; 

So when when I want to give the adapter another set of data, another array (with one item for example), what should I do?

like image 632
Sandra Avatar asked Oct 29 '14 16:10

Sandra


People also ask

How do I change data in RecyclerView?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − Open build. gradle and add Recycler view & Card view library dependencies. Step 3 − Add the following code to res/layout/activity_main.

What is the use of ViewHolder in RecyclerView Android?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive View.

What is recycler view?

RecyclerView is the ViewGroup that contains the views corresponding to your data. It's a view itself, so you add RecyclerView into your layout the way you would add any other UI element. Each individual element in the list is defined by a view holder object.

What is notifyItemChanged in Android?

notifyItemChanged. Notify any registered observers that the item at position has changed with an optional payload object. This is an item change event, not a structural change event. It indicates that any reflection of the data at position is out of date and should be updated.


1 Answers

If you have stable ids in your adapter, you can get pretty good results (animations) if you create a new array containing the filtered items and call

recyclerView.swapAdapter(newAdapter, false); 

Using swapAdapter hints RecyclerView that it can re-use view holders. (vs in setAdapter, it has to recycle all views and re-create because it does not know that the new adapter has the same ViewHolder set with the old adapter).

A better approach would be finding which items are removed and calling notifyItemRemoved(index). Don't forget to actually remove the item. This will let RecyclerView run predictive animations. Assuming you have an Adapter that internally uses an ArrayList, implementation would look like this:

// adapter code final List<ItemData> mItems = new ArrayList(); //contains your items public void filterOut(String filter) {    final int size = mItems.size();    for(int i = size - 1; i>= 0; i--) {        if (mItems.get(i).test(filter) == false) {            mItems.remove(i);            notifyItemRemoved(i);        }    } } 

It would perform even better if you can batch notifyItemRemoved calls and use notifyItemRangeRemoved instead. It would look sth like: (not tested)

public void filterOut(String filter) {    final int size = mItems.size();    int batchCount = 0; // continuous # of items that are being removed    for(int i = size - 1; i>= 0; i--) {        if (mItems.get(i).test(filter) == false) {            mItems.remove(i);            batchCount ++;        } else if (batchCount != 0) { // dispatch batch            notifyItemRangeRemoved(i + 1, batchCount);            batchCount = 0;        }    }    // notify for remaining    if (batchCount != 0) { // dispatch remaining        notifyItemRangeRemoved(0, batchCount);    } } 

You need to extend this code to add items that were previously filtered out but now should be visible (e.g. user deletes the filter query) but I think this one should give the basic idea.

Keep in mind that, each notify item call affects the ones after it (which is why I'm traversing the list from end to avoid it). Traversing from end also helps ArrayList's remove method performance (less items to shift).

For example, if you were traversing the list from the beginning and remove the first two items. You should either call

notifyItemRangeRemoved(0, 2); // 2 items starting from index 0 

or if you dispatch them one by one

notifyItemRemoved(0); notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0 
like image 60
yigit Avatar answered Oct 20 '22 02:10

yigit