管理 RecyclerView 状态

RecyclerView 可以使用尽可能少的图形资源显示大量数据。当用户滚动浏览 RecyclerView 中的项时,系统会重复使用已滚动到界面外的项的 View 实例,随着项在屏幕上滚动而创建新的项。但是,配置更改(例如设备旋转)可以重置 RecyclerView 的状态,迫使用户重新滚动到之前在项列表中的位置。

RecyclerView 应在所有配置更改期间保持其状态(特别是滚动位置)及其列表元素的状态。

保持状态

设置 RecyclerView.Adapter 的状态恢复政策以保存 RecyclerView 滚动位置。保存 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. 保存有状态列表项的状态

保存复杂 RecyclerView 列表项(例如包含 EditText 元素的项)的状态。例如,如需保存 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.
    }
});

ActivityFragment 中声明回调。使用 ViewModel 存储状态。

3. 将列表项状态添加到 Adapter

将列表项的状态添加到 RecyclerView.Adapter。在您的主机 ActivityFragment 被创建后,将项状态传递到适配器构造函数:

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 能够恢复其滚动位置以及 RecyclerView 列表中每个项的状态。

包含本指南的集合

本指南属于以下精选快速入门指南集合,这些指南涵盖了更广泛的 Android 开发目标:

让您的应用能够在平板电脑、可折叠设备和 ChromeOS 设备上提供优化的用户体验。

有问题或反馈

请访问我们的常见问题解答页面,了解简短指南,或与我们联系,告诉我们您的想法。