web-dev-qa-db-ja.com

RecyclerView-アイテムの更新と移動を同時に行う方法

SortedListに裏打ちされたRecyclerViewアダプターがあります。アイテムに変更を加えると、アイテムが変更され、リスト内で再配置されます。

アイテムの開始位置または終了位置のいずれかでnotifyItemChangedを使用すると、前後のnotifyItemMovedと組み合わせても効果がないように見えることがわかりました。

notifyItemMovedを使用すると、動きのアニメーションが正しくトリガーされますが、ビューは変更されず、古い情報が表示されます。

notifyDatasetChangedを使用すると、行が更新されてから移動されますが、順番に移動されるため、速度が遅く、リスト全体に通知されるため、必ずしも望ましくありません。

移動アニメーションと更新アニメーションを組み合わせる方法はありますか?そして、なぜnotifyItemChangedは何もしないのですか?

10
TBridges42

RecyclerView.Adapter reference では、notifyItemMoved()は単なる構造上の変更であるため、データは更新されないと言われています。一方、notifyItemChanged()はデータ変更と言われています。

notifyItemChanged()を呼び出すと、RecyclerView#onBindViewHolder()が呼び出されるため、ビューが更新されます。

更新と移動のための私にとっての作業アプローチは次のとおりです。

notifyItemChanged(oldPos); notifyItemMoved(oldPos, newPos);

4
mlyko

次を使用できます。

SortedList.updateItemAt(int position, Objet newItem)

newItemは更新されたアイテムであり、positionは現在の位置です。このメソッドは、現在のアイテムをnewItemに置き換え、リスト(およびそのリサイクラービューリンク)に再配置します。

ここ は公式ドキュメントです。

これがお役に立てば幸いです。

2
J. Manuel

DiffUtilを見てください https://developer.Android.com/reference/Android/support/v7/util/DiffUtil.html

アダプタ内でデータセットを更新すると、このツールを使用して、新しいデータセットを正しく表すために必要な通知を計算できます。

  1. 延長DiffUtil.CallbackそしてAbstractメソッドを実装します(私は次のようなコンストラクターを作成します:

    public MyDiffCallback(ArrayList<String> oldList, ArrayList<String> newList) {
    
        this.oldList = oldList;
        this.newList = newList;
    }
    

実装できるように、oldListnewListをメモリに保持します。

areItemsTheSameareContentsTheSamegetNewListSizegetOldListSize

例えば:

@Override
public int getOldListSize() {
    return oldList.size();
}
@Override
public int getNewListSize() {
    return newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
    return oldList.get(oldItemPosition).equals(newList(newItemPosition))
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
    return areItemsTheSame(oldItemPosition, newItemPosition);
}

areItemsTheSame:アイテムが移動したかどうかをUTILに通知します(位置を確認)areContentsTheSame:アイテムの内容が変更されたかどうかをUTILに通知します。

ここで、updateDataSetメソッド(またはあなたがそれを呼んだものなら何でも!);次のようなことをします:

public updateDataSet(List newDataSet) {
    // this.dataSet is the old data set / List
    final MyDiffCallback callback = new MyDiffCallback(this.dataSet, newDataSet);
    final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(callback);

    this.dataSet = newDataSet;
    diffResult.dispatchUpdatesTo(this); //This is the Adapter
}

これがお役に立てば幸い、Gav

参照: https://medium.com/@iammert/using-diffutil-in-Android-recyclerview-bdca8e4fbb00#.yhxirkkq6

1
Gavin Harris