Android:如何复制ListAdapter列表实现列表项移动并更新UI?
关于ListAdapter实现列表项移动的问题
我该如何复制现有ListAdapter的列表,以便用于移动列表项,然后通过对比新的复制列表与原列表来更新UI?
或许Android开发者在设计用于RecyclerView的ListAdapter源码时,只考虑了CRUD操作。若是如此,他们忽略了过滤、排序和移动列表项等其他重要的RecyclerView操作。这些操作仅会改变排序顺序(排序和移动项)或从原列表中移除部分项(过滤),但这难道需要自定义Adapter吗?此外,对于大型RecyclerView列表,需要将列表复制到内存中让ListAdapter“识别”新列表,这似乎违背了ListAdapter在后台线程提升效率的初衷。
我原本认为后台线程更新对稳定性和UI效率很有价值,因此将现有项目转为使用ListAdapter。我的CRUD操作运行正常,但现在面临的难题是如何实现过滤、排序和移动列表项这些功能。
我尝试移动RecyclerView中的列表项,但拖拽功能无法正常工作。以下是我至今尝试过的不同组合方法。同时,我查阅了所有关于ListAdapter的问题……但遗憾的是我完全不懂Kotlin,所以寻求Java解决方案。我遗漏了什么?
MainActivity方案#1
ItemTouchHelper.SimpleCallback itemTouchHelperCallback1 = new ItemTouchHelper.SimpleCallback( (ItemTouchHelper.UP | ItemTouchHelper.DOWN),0) { int dragFrom = -1; int dragTo = -1; @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { int fromPos = viewHolder.getBindingAdapterPosition(); int toPos = target.getBindingAdapterPosition(); if (dragFrom == -1) { dragFrom = fromPos; } dragTo = toPos; cardsAdapter.moveItem(fromPos, toPos); return true; } }; new ItemTouchHelper(itemTouchHelperCallback1).attachToRecyclerView(recyclerView);
MainActivity方案#2(onMove()方法)
List newList = adapter.getCurrentList(); Quickcard quickcardItem = newList.get(fromPos); newList.remove(fromPos); newList.add(toPos, quickcardItem); cardsAdapter.moveItem(fromPos, toPos); cardsAdapter.notifyItemMoved(fromPos, toPos); cardsAdapter.submitList(newList); return true;
ListAdapter方案#1
public class CardsAdapter extends ListAdapter<Quickcard, CardsAdapter.ItemHolder> { private final LayoutInflater layoutInflater; protected CardsAdapter(@NonNull LayoutInflater layoutInflater, DiffUtil.ItemCallback<Quickcard> diffCallback) { super(diffCallback); this.layoutInflater = layoutInflater; } ... // ViewHolder代码 public void moveItem(int fromOldPos, int toNewPos) { // 复制ListAdapter的现有列表 ArrayList<Quickcard> currList = new ArrayList<>(getCurrentList()); if (fromOldPos == toNewPos) { return; } Collections.swap(currList, toNewPos, fromOldPos); notifyItemMoved(fromOldPos, toNewPos); submitList(currList); } }
ListAdapter方案#2(moveItem()方法)
List<Quickcard> currList = getCurrentList(); List<Quickcard> copiedList = new ArrayList<>(currList); if (fromOldPos == toNewPos) { return; } if (fromOldPos < toNewPos) { // 项在列表中向下移动 for (int i = fromOldPos; i < toNewPos; i++) { Collections.swap(copiedList, i,i + 1); } } else { // 项在列表中向上移动 for (int i = fromOldPos; i > toNewPos; i--) { Collections.swap(copiedList, i,i - 1); } } notifyItemMoved(fromOldPos, toNewPos); submitList(copiedList);
ListAdapter方案#3(moveItem()方法)
// 为Model添加复制构造函数后,我还尝试了此方法
// (参考StackOverflow #48575477中@Matt的回答)
List<CustomObject> copyList = new ArrayList<>(); for(CustomObject obj : parentList) { copyList.add(new CustomObject(obj)); }
ViewModel方案
// mTodos是ViewModel中的MutableLiveData<List> List<Todo> todos = mTodos.getValue(); ArrayList<Todo> clonedTodos = new ArrayList<Todo>(todos.size()); for(int i = 0; i < todos.size(); i++){ clonedTodos.add(new Todo(todos.get(i))); } mTodos.postValue(clonedTodos);
内容的提问来源于stack exchange,提问作者AJW
相关产品推荐
相关产品推荐

