gig*_*ig6 6 java android android-recyclerview itemtouchhelper android-listadapter
我正在使用 ItemTouchHelper 类来支持 RecyclerView 中的拖放。我有一个按预期工作的实现,但它似乎效率很低。在我的 onMoved 方法中,我获取列表的当前版本,交换拖动的项目,然后使用新版本的列表调用 SubmitList。问题是,每次发生交换时都会调用 onMoved,并且交换在列表中拖动时会一一执行。因此,如果位置 1 处的项目被拖动到位置 11,则每次交换时都会调用 onMoved (1 -> 2) 、 (2 -> 3) 等。这意味着我获得了列表的新版本,并在拖动完成时调用了 SubmitList 10 次。
我尝试过的:
我尝试在拖动完成后使用更新的列表调用submitList,但它没有改变。我在调用submitList之前记录了适配器的getCurrentList(),它显示了原始的未更改列表(这是预期的)。我已经记录了 MainActivity 的 currentList 变量,它显示了更新的交换列表。我将 currentList 变量传递给submitList,然后记录适配器的 getCurrentList(),它仍然显示原始未更改的列表。我已阅读这篇文章,但建议的解决方案均无效。任何帮助,将不胜感激!
编辑:我还在适配器中使用 DiffUtil。
MainActivity.java
...
private void createItemTouchHelper() {
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP | ItemTouchHelper.DOWN,
ItemTouchHelper.START | ItemTouchHelper.END) {
// To track changes when user drags
List<ListItem> currentList;
// This method is called when user starts dragging an item
public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) {
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
// get the current list from the adapter to modify
// have to create new list because getCurrentList() returns an unmodifiable list
currentList = new ArrayList<>(adapterMain.getCurrentList());
}
}
// This method gets called when user releases the dragged item
public void clearView(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder) {
adapterMain.submitList(currentList); // Does not update the list in the adapter
}
// gets called each time a row is dragged by one position
public void onMoved(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder source, int fromPos,
@NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
Collections.swap(currentList, toPos, fromPos); // update the local ArrayList
// This "visually" moves the item in RecyclerView but it doesn't update the list in the adapter
adapterMain.notifyItemMoved(fromPos, toPos);
}
}).attachToRecyclerView(recyclerMain);
}
Run Code Online (Sandbox Code Playgroud)
这是 onMoved 方法的工作版本。我不必在 onSelectedChanged() 或clearView() 中添加任何代码即可使其工作。虽然看起来效率很低...
public void onMoved(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder source, int fromPos,
@NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
// adapterMain.getCurrentList() returns an unmodifiable list, convert to new ArrayList
currentList = new ArrayList<>(adapterMain.getCurrentList());
Collections.swap(currentList, toPos, fromPos);
adapterMain.submitList(currentList); // why does submitList work here but not in the clearView method?
// adapterMain.notifyItemMoved(fromPos, toPos); // this is not needed when I call submitList here
}
Run Code Online (Sandbox Code Playgroud)
RecyclerAdapterMain.java
public class RecyclerAdapterMain extends ListAdapter<ListItem, RecyclerAdapterMain.ListItemHolder> {
public RecyclerAdapterMain() {
super(DIFF_CALLBACK);
}
private static final DiffUtil.ItemCallback<ListItem> DIFF_CALLBACK = new DiffUtil.ItemCallback<ListItem>() {
@Override
public boolean areItemsTheSame(@NonNull ListItem oldItem, @NonNull ListItem newItem) {
return oldItem.getId() == newItem.getId();
}
@Override
public boolean areContentsTheSame(@NonNull ListItem oldItem, @NonNull ListItem newItem) {
return oldItem.equals(newItem);
}
};
...
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
815 次 |
最近记录: |