diff --git a/app/src/main/java/org/linphone/chat/ChatRoomsAdapter.java b/app/src/main/java/org/linphone/chat/ChatRoomsAdapter.java index c4b318ed5..690437678 100644 --- a/app/src/main/java/org/linphone/chat/ChatRoomsAdapter.java +++ b/app/src/main/java/org/linphone/chat/ChatRoomsAdapter.java @@ -23,6 +23,7 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import androidx.recyclerview.widget.DiffUtil; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; @@ -74,14 +75,15 @@ public class ChatRoomsAdapter extends SelectableAdapter { public void refresh() { ChatRoom[] rooms = LinphoneManager.getCore().getChatRooms(); + List roomsList; if (mContext.getResources().getBoolean(R.bool.hide_empty_one_to_one_chat_rooms)) { - mRooms = LinphoneUtils.removeEmptyOneToOneChatRooms(rooms); + roomsList = LinphoneUtils.removeEmptyOneToOneChatRooms(rooms); } else { - mRooms = Arrays.asList(rooms); + roomsList = Arrays.asList(rooms); } Collections.sort( - mRooms, + roomsList, new Comparator() { public int compare(ChatRoom cr1, ChatRoom cr2) { long timeDiff = cr1.getLastUpdateTime() - cr2.getLastUpdateTime(); @@ -91,7 +93,10 @@ public class ChatRoomsAdapter extends SelectableAdapter { } }); - notifyDataSetChanged(); + DiffUtil.DiffResult diffResult = + DiffUtil.calculateDiff(new ChatRoomDiffCallback(roomsList, mRooms)); + diffResult.dispatchUpdatesTo(this); + mRooms = roomsList; } public void clear() { @@ -114,4 +119,37 @@ public class ChatRoomsAdapter extends SelectableAdapter { public long getItemId(int position) { return position; } + + class ChatRoomDiffCallback extends DiffUtil.Callback { + List oldChatRooms; + List newChatRooms; + + public ChatRoomDiffCallback(List newRooms, List oldRooms) { + oldChatRooms = oldRooms; + newChatRooms = newRooms; + } + + @Override + public int getOldListSize() { + return oldChatRooms.size(); + } + + @Override + public int getNewListSize() { + return newChatRooms.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + ChatRoom oldRoom = oldChatRooms.get(oldItemPosition); + ChatRoom newRoom = newChatRooms.get(newItemPosition); + return oldRoom.getLocalAddress().weakEqual(newRoom.getLocalAddress()) + && oldRoom.getPeerAddress().weakEqual(newRoom.getPeerAddress()); + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + return oldChatRooms.get(oldItemPosition).equals(newChatRooms.get(newItemPosition)); + } + } } diff --git a/app/src/main/java/org/linphone/chat/ChatRoomsFragment.java b/app/src/main/java/org/linphone/chat/ChatRoomsFragment.java index 4c9a217a9..6a341b058 100644 --- a/app/src/main/java/org/linphone/chat/ChatRoomsFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatRoomsFragment.java @@ -267,7 +267,7 @@ public class ChatRoomsFragment extends Fragment public void onContactsUpdated() { ChatRoomsAdapter adapter = (ChatRoomsAdapter) mChatRoomsList.getAdapter(); if (adapter != null) { - adapter.notifyDataSetChanged(); + adapter.refresh(); } } diff --git a/app/src/main/java/org/linphone/views/LinphoneLinearLayoutManager.java b/app/src/main/java/org/linphone/views/LinphoneLinearLayoutManager.java index fcc2dbc57..afddc5200 100644 --- a/app/src/main/java/org/linphone/views/LinphoneLinearLayoutManager.java +++ b/app/src/main/java/org/linphone/views/LinphoneLinearLayoutManager.java @@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import android.content.Context; import android.util.AttributeSet; import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import org.linphone.core.tools.Log; /* https://stackoverflow.com/questions/30220771/recyclerview-inconsistency-detected-invalid-item-position */ public class LinphoneLinearLayoutManager extends LinearLayoutManager { @@ -46,4 +48,13 @@ public class LinphoneLinearLayoutManager extends LinearLayoutManager { Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + try { + super.onLayoutChildren(recycler, state); + } catch (IndexOutOfBoundsException e) { + Log.w("[LinearLayoutManager] Index out of bounds exception successfully catched..."); + } + } }