Android の RecyclerView では DiffUtil を使用することで変更前後のリストアイテムの差分を計算して、その結果(アイテムの追加、削除、変更、移動)に応じて適切なアニメーションで RecyclerView を更新してくれます。
参考記事: DiffUtilを使ってRecyclerView.Adapterをいい感じにする
この仕組みを使ってランキング表示のようにアイテムが上下に移動するようなビューを実装していた際に、下位のアイテムが先頭に移動するケースで僕の意図しない動作となってしまったため、その対策方法のメモです。
先頭にアイテムを移動した時に隠れてしまう
下図のとおり A~J の10個のアイテムがあり、スクリーンには先頭から8個のアイテムが表示されている状態を例とします。
ここでアイテム E のランキングが上がって先頭にくるような場合、僕の期待する結果としてはアイテム E が先頭に移動してスクリーン上に表示されている状態なのですが、実際に DiffUtil による RecyclerView の更新結果はスクリーンより上側の隠れた位置に移動してしまいました。これを何とかしたい。
先頭にダミーアイテムを置くことで解決する
結論として、RecyclerView の先頭に常に見えないダミーアイテムを置いておくことで解決しました。
RecyclerView では下記の参考記事にあるとおり、viewType を上手く利用することで、アイテムごとに ViewHolder を切り替えることができるため、先頭のダミーアイテムについてはスクリーン上には表示されない(高さ0の)ビューを置いておきます。
参考記事: RecyclerViewでセクション分けをする
この状態でアイテム E が先頭に移動する時は、実際にはダミーアイテムの下に移動することになり、僕の期待していた結果が得られるようになりました。