RecyclerView
では、最小限のグラフィック リソースを使用して大量のデータを表示できます。ユーザーが RecyclerView
内のアイテムをスクロールすると、画面外にスクロールしたアイテムの View
インスタンスが再使用され、画面上でのスクロール時に新しいアイテムが作成されます。しかし、デバイスの回転などの構成変更により、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
: アクティビティまたはフラグメントの状態を保持します。
結果
RecyclerView
は、スクロール位置と RecyclerView
リスト内のすべてのアイテムの状態を復元できるようになりました。
このガイドを含むコレクション
このガイドは、Android 開発の幅広い目標を網羅する、厳選されたクイックガイド コレクションの一部です。
![](https://developer.android.google.cn/static/images/quick-guides/collection-illustration.png?hl=ja)