K.Os
K.Os

Reputation: 5506

How to properly notifyItemMoved, insert and removed in RecyclerView old data list when i get new fresh list to assign to it

I am populating new data in my RecyclerView adapter all at once, so there are no insert or remove one item actions.

So simply, i have an old list and when some Event occurs i get the new list and i can assign the new list to the old.

Problems are i cannot make properly the animation for each item in the old list

Here is something i have now, which i thought will work for first case - item move to new position:

     if(currentAdapterData!= null){
            for(int i = 0; i < currentAdapterData.size(); i++){
                for(int j = 0; j < newData.size(); j++){
                    if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
                        Log.v("same item", "currentAdapterData index :" + i  + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
                        if(i != j){
                            notifyItemMoved(i, j);
                        }
                    }
                }
            }
        }

        currentAdapterData = newData;

However it does not work as expected, and there is difference between logs(which are correct) and the list appearing on the phone(with wrong items positions, some duplicates, buggy etc.)

So how can i make it work? With notifyItemMoved, notifyItemInserted and notifyItemRemoved?

I don't want to just use NofifyDataSetChanged, because it refresh the entire list instead of just updating the items with animations that have changed.

Upvotes: 1

Views: 1425

Answers (3)

Sambhav Khandelwal
Sambhav Khandelwal

Reputation: 3765

Well for this ,I feel this would be the easiest.Just follow it ->

Replace this

if(currentAdapterData!= null){
        for(int i = 0; i < currentAdapterData.size(); i++){
            for(int j = 0; j < newData.size(); j++){
                if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
                    Log.v("same item", "currentAdapterData index :" + i  + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
                    if(i != j){
                        notifyItemMoved(i, j);
                    }
                }
            }
        }
    }

    currentAdapterData = newData;

with

if(currentAdapterData!= null){
        for(int i = 0; i < currentAdapterData.size(); i++){
            for(int j = 0; j < newData.size(); j++){
                if(currentAdapterData.get(i).getSomeIdentifier().equals(newData.get(j).getSomeIdentifier())){
                    Log.v("same item", "currentAdapterData index :" + i  + " ," + currentAdapterData.get(i).getSomeIdentifier() + " == newData index: " + j + " ," + newData.get(j).getSomeIdentifier());
                    if(i != j){
                        notifyDataSetChanged();
                       new CountDownTimer(250, 250) {

                                @Override
                                public void onTick(long millisUntilFinished) {
                                    Log.d("millisUntilFinished", "" + millisUntilFinished);
                                }

                                @Override
                                public void onFinish() {
                                    notifyItemMoved(i, j);
                                }
                        }.start();                      
                    }
                }
            }
        }
    }

this will update the values and after 250 millisecond(1/4th a second),the value with be moved with animation.

Upvotes: 0

elmorabea
elmorabea

Reputation: 3263

It looks like that your new data is also a form of list, not a single item. I think this could be a good candidate for using DiffUtil in the support library. Here is also a nice tutorial for it.

It will allow you to calculate the difference in the new data and only update needed fields. It will also offload the work asynchronously.

You just need to implement a DiffUtil.Callback to indicate if your items are the same or the contents are the same.

You update your recyclerView like that:

DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
diffResult.dispatchUpdatesTo(yourAdapter);

Upvotes: 3

Rahul Baboria
Rahul Baboria

Reputation: 21

Simply use DiffUtil like

final MyDiffCallback diffCallback = new MyDiffCallback(prevList, newList); final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);

Create a Callback by extending MyDiffCallback and override methods and do as needed.

public class MyDiffCallback extends DiffUtil.Callback

// override methods

Upvotes: 1

Related Questions