RecyclerView では、最小限のグラフィック リソースを使用して大量のデータを表示できます。ユーザーが RecyclerView のアイテムをスクロールすると、画面外にスクロールしたアイテムの View インスタンスが再利用され、画面上でのスクロール時に新しいアイテムが作成されます。しかし、デバイスの回転などの構成変更により、RecyclerView の状態がリセットされ、ユーザーがアイテムのリストの以前の位置に再びスクロールしなければならない場合があります。
RecyclerView は、すべての構成変更において、状態(特にスクロール位置)とリスト要素の状態を維持する必要があります。
結果
RecyclerView は、スクロール位置と RecyclerView リスト内のすべてのアイテムの状態を復元できます。
状態の維持
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 開発のより広範な目標を対象とした、厳選されたクイック ガイド コレクションの一部です。