管理 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 处理程序的 callback 来捕获文本更改。在 callback 中,定义要保存哪些数据

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 中声明 callback。使用 ViewModel 来存储状态。

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

将列表项目的状态添加到您的 RecyclerView.Adapter 中。在创建您的 host 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 设备上提供优化的用户体验。

有问题或反馈

前往我们的常见问题页面,了解快速指南,或联系我们,告诉我们您的想法。