RecyclerView では、最小限のグラフィック リソースを使用して大量のデータを表示できます。ユーザーが RecyclerView のアイテムをスクロールすると、画面外にスクロールしたアイテムの View インスタンスが再利用され、画面上でのスクロール時に新しいアイテムが作成されます。しかし、デバイスの回転などの構成変更により、RecyclerView の状態がリセットされ、ユーザーがアイテムのリストの以前の位置に再びスクロールしなければならない場合があります。
RecyclerView は、すべての構成変更において、状態(特にスクロール位置)とリスト要素の状態を維持する必要があります。
結果
RecyclerView は、スクロール位置と RecyclerView リスト内のすべてのアイテムの状態を復元できます。
バージョンの互換性
この実装はすべての API レベルに対応しています。
依存関係
なし。
状態の維持
RecyclerView のスクロール位置を保存するように RecyclerView.Adapter の状態復元ポリシーを設定します。RecyclerView のリストアイテムの状態を保存します。RecyclerView アダプターにリストアイテムの状態を追加し、ViewHolder にバインドされたときにリストアイテムの状態を復元します。
1. Adapter の状態復元ポリシーを有効にする
RecyclerView アダプターの状態復元ポリシーを有効にして、構成変更後も RecyclerView のスクロール位置が維持されるようにします。ポリシー仕様をアダプター コンストラクタに追加します。
Kotlin
class MyAdapter() : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
init {
stateRestorationPolicy = StateRestorationPolicy.PREVENT_WHEN_EMPTY
}
...
}
Java
class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public Adapter() {
setStateRestorationPolicy(StateRestorationPolicy.PREVENT_WHEN_EMPTY);
}
...
}
2. ステートフルなリストアイテムの状態を保存する
EditText 要素を含むアイテムなど、複雑な RecyclerView リストアイテムの状態を保存します。たとえば、EditText の状態を保存するには、テキストの変更をキャプチャする onClick ハンドラと同様のコールバックを追加します。コールバック内で、保存するデータを定義します。
Kotlin
input.addTextChangedListener(
afterTextChanged = { text ->
text?.let {
// Save state here.
}
}
)
Java
input.addTextChangedListener(new TextWatcher() {
...
@Override
public void afterTextChanged(Editable s) {
// Save state here.
}
});
Activity または Fragment でコールバックを宣言します。ViewModel を使用して状態を保存します。
3. Adapter にリストアイテムの状態を追加する
リストアイテムの状態を RecyclerView.Adapter に追加します。ホスト Activity または Fragment が作成されたときに、アイテムの状態をアダプター コンストラクタに渡します。
Kotlin
val adapter = MyAdapter(items, viewModel.retrieveState())
Java
MyAdapter adapter = new MyAdapter(items, viewModel.retrieveState());
4. アダプターの ViewHolder でリストアイテムの状態を復元する
RecyclerView.Adapter で ViewHolder をアイテムにバインドする際に、アイテムの状態を復元します。
Kotlin
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
...
val item = items[position]
val state = states.firstOrNull { it.item == item }
if (state != null) {
holder.restore(state)
}
}
Java
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
...
Item item = items[position];
Arrays.stream(states).filter(state -> state.item == item)
.findFirst()
.ifPresent(state -> holder.restore(state));
}
要点
RecyclerView.Adapter#setStateRestorationPolicy(): 構成変更後にRecyclerView.Adapterが状態を復元する方法を指定します。ViewModel: アクティビティまたはフラグメントの状態を保持します。
このガイドを含むコレクション
このガイドは、Android 開発のより広範な目標を対象とした、厳選されたクイックガイド コレクションの一部です。