How to update RecyclerView Adapter Data?

前端 未结 13 2322
误落风尘
误落风尘 2020-11-22 03:48

Trying to figure out what is the issue with updating RecyclerView\'s Adapter.

After I get a new List of products, I tried to:

  1. Update t

相关标签:
13条回答
  • 2020-11-22 04:11

    This is a general answer for future visitors. The various ways to update the adapter data are explained. The process includes two main steps every time:

    1. Update the data set
    2. Notify the adapter of the change

    Insert single item

    Add "Pig" at index 2.

    Insert single item

    String item = "Pig";
    int insertIndex = 2;
    data.add(insertIndex, item);
    adapter.notifyItemInserted(insertIndex);
    

    Insert multiple items

    Insert three more animals at index 2.

    Insert multiple items

    ArrayList<String> items = new ArrayList<>();
    items.add("Pig");
    items.add("Chicken");
    items.add("Dog");
    int insertIndex = 2;
    data.addAll(insertIndex, items);
    adapter.notifyItemRangeInserted(insertIndex, items.size());
    

    Remove single item

    Remove "Pig" from the list.

    Remove single item

    int removeIndex = 2;
    data.remove(removeIndex);
    adapter.notifyItemRemoved(removeIndex);
    

    Remove multiple items

    Remove "Camel" and "Sheep" from the list.

    Remove multiple items

    int startIndex = 2; // inclusive
    int endIndex = 4;   // exclusive
    int count = endIndex - startIndex; // 2 items will be removed
    data.subList(startIndex, endIndex).clear();
    adapter.notifyItemRangeRemoved(startIndex, count);
    

    Remove all items

    Clear the whole list.

    Remove all items

    data.clear();
    adapter.notifyDataSetChanged();
    

    Replace old list with new list

    Clear the old list then add a new one.

    Replace old list with new list

    // clear old list
    data.clear();
    
    // add new list
    ArrayList<String> newList = new ArrayList<>();
    newList.add("Lion");
    newList.add("Wolf");
    newList.add("Bear");
    data.addAll(newList);
    
    // notify adapter
    adapter.notifyDataSetChanged();
    

    The adapter has a reference to data, so it is important that I didn't set data to a new object. Instead I cleared the old items from data and then added the new ones.

    Update single item

    Change the "Sheep" item so that it says "I like sheep."

    Update single item

    String newValue = "I like sheep.";
    int updateIndex = 3;
    data.set(updateIndex, newValue);
    adapter.notifyItemChanged(updateIndex);
    

    Move single item

    Move "Sheep" from position 3 to position 1.

    Move single item

    int fromPosition = 3;
    int toPosition = 1;
    
    // update data array
    String item = data.get(fromPosition);
    data.remove(fromPosition);
    data.add(toPosition, item);
    
    // notify adapter
    adapter.notifyItemMoved(fromPosition, toPosition);
    

    Code

    Here is the project code for your reference. The RecyclerView Adapter code can be found at this answer.

    MainActivity.java

    public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {
    
        List<String> data;
        MyRecyclerViewAdapter adapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            // data to populate the RecyclerView with
            data = new ArrayList<>();
            data.add("Horse");
            data.add("Cow");
            data.add("Camel");
            data.add("Sheep");
            data.add("Goat");
    
            // set up the RecyclerView
            RecyclerView recyclerView = findViewById(R.id.rvAnimals);
            LinearLayoutManager layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);
            DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(),
                    layoutManager.getOrientation());
            recyclerView.addItemDecoration(dividerItemDecoration);
            adapter = new MyRecyclerViewAdapter(this, data);
            adapter.setClickListener(this);
            recyclerView.setAdapter(adapter);
        }
    
        @Override
        public void onItemClick(View view, int position) {
            Toast.makeText(this, "You clicked " + adapter.getItem(position) + " on row number " + position, Toast.LENGTH_SHORT).show();
        }
    
        public void onButtonClick(View view) {
            insertSingleItem();
        }
    
        private void insertSingleItem() {
            String item = "Pig";
            int insertIndex = 2;
            data.add(insertIndex, item);
            adapter.notifyItemInserted(insertIndex);
        }
    
        private void insertMultipleItems() {
            ArrayList<String> items = new ArrayList<>();
            items.add("Pig");
            items.add("Chicken");
            items.add("Dog");
            int insertIndex = 2;
            data.addAll(insertIndex, items);
            adapter.notifyItemRangeInserted(insertIndex, items.size());
        }
    
        private void removeSingleItem() {
            int removeIndex = 2;
            data.remove(removeIndex);
            adapter.notifyItemRemoved(removeIndex);
        }
    
        private void removeMultipleItems() {
            int startIndex = 2; // inclusive
            int endIndex = 4;   // exclusive
            int count = endIndex - startIndex; // 2 items will be removed
            data.subList(startIndex, endIndex).clear();
            adapter.notifyItemRangeRemoved(startIndex, count);
        }
    
        private void removeAllItems() {
            data.clear();
            adapter.notifyDataSetChanged();
        }
    
        private void replaceOldListWithNewList() {
            // clear old list
            data.clear();
    
            // add new list
            ArrayList<String> newList = new ArrayList<>();
            newList.add("Lion");
            newList.add("Wolf");
            newList.add("Bear");
            data.addAll(newList);
    
            // notify adapter
            adapter.notifyDataSetChanged();
        }
    
        private void updateSingleItem() {
            String newValue = "I like sheep.";
            int updateIndex = 3;
            data.set(updateIndex, newValue);
            adapter.notifyItemChanged(updateIndex);
        }
    
        private void moveSingleItem() {
            int fromPosition = 3;
            int toPosition = 1;
    
            // update data array
            String item = data.get(fromPosition);
            data.remove(fromPosition);
            data.add(toPosition, item);
    
            // notify adapter
            adapter.notifyItemMoved(fromPosition, toPosition);
        }
    }
    

    Notes

    • If you use notifyDataSetChanged(), then no animation will be performed. This can also be an expensive operation, so it is not recommended to use notifyDataSetChanged() if you are only updating a single item or a range of items.
    • Check out DiffUtil if you are making large or complex changes to a list.

    Further study

    • CodePath: Using the RecyclerView
    • Smart way to update RecyclerView using DiffUtil
    0 讨论(0)
  • 2020-11-22 04:12

    Another option is to use diffutil . It will compare the original list against the new list and use the new list as the update if there is a change.

    Basically, we can use DiffUtil to compare the old data vs new data and let it call notifyItemRangeRemoved, and notifyItemRangeChanged and notifyItemRangeInserted on your behalf.

    A quick example of using diffUtil instead of notifyDataSetChanged:

    DiffResult diffResult = DiffUtil
                    .calculateDiff(new MyDiffUtilCB(getItems(), items));
    
    //any clear up on memory here and then
    diffResult.dispatchUpdatesTo(this);
    
    //and then, if necessary
    items.clear()
    items.addAll(newItems)
    

    I do the calculateDiff work off the main thread in case it's a big list.

    0 讨论(0)
  • 2020-11-22 04:14

    i got the answer after a long time

      SELECTEDROW.add(dt);
                    notifyItemInserted(position);
                    SELECTEDROW.remove(position);
                    notifyItemRemoved(position);
    
    0 讨论(0)
  • 2020-11-22 04:22

    I found out that a really simple way to reload the RecyclerView is to just call

    recyclerView.removeAllViews();
    

    This will first remove all content of the RecyclerView and then add it again with the updated values.

    0 讨论(0)
  • 2020-11-22 04:23

    The best and the coolest way to add new data to the present data is

     ArrayList<String> newItems = new ArrayList<String>();
     newItems = getList();
     int oldListItemscount = alcontainerDetails.size();
     alcontainerDetails.addAll(newItems);           
     recyclerview.getAdapter().notifyItemChanged(oldListItemscount+1, al_containerDetails);
    
    0 讨论(0)
  • 2020-11-22 04:24

    These methods are efficient and good to start using a basic RecyclerView.

    private List<YourItem> items;
    
    public void setItems(List<YourItem> newItems)
    {
        clearItems();
        addItems(newItems);
    }
    
    public void addItem(YourItem item, int position)
    {
        if (position > items.size()) return;
    
        items.add(item);
        notifyItemInserted(position);
    }
    
    public void addMoreItems(List<YourItem> newItems)
    {
        int position = items.size() + 1;
        newItems.addAll(newItems);
        notifyItemChanged(position, newItems);
    }
    
    public void addItems(List<YourItem> newItems)
    {
        items.addAll(newItems);
        notifyDataSetChanged();
    }
    
    public void clearItems()
    {
        items.clear();
        notifyDataSetChanged();
    }
    
    public void addLoader()
    {
        items.add(null);
        notifyItemInserted(items.size() - 1);
    }
    
    public void removeLoader()
    {
        items.remove(items.size() - 1);
        notifyItemRemoved(items.size());
    }
    
    public void removeItem(int position)
    {
        if (position >= items.size()) return;
    
        items.remove(position);
        notifyItemRemoved(position);
    }
    
    public void swapItems(int positionA, int positionB)
    {
        if (positionA > items.size()) return;
        if (positionB > items.size()) return;
    
        YourItem firstItem = items.get(positionA);
    
        videoList.set(positionA, items.get(positionB));
        videoList.set(positionB, firstItem);
    
        notifyDataSetChanged();
    }
    

    You can implement them inside of an Adapter Class or in your Fragment or Activity but in that case you have to instantiate the Adapter to call the notification methods. In my case I usually implement it in the Adapter.

    0 讨论(0)
提交回复
热议问题