Android Room+LiveData更新数据后如何恢复RecyclerView滚动位置
问题根因与解决方案
1. 滚动位置自动回到顶部的原因
你最初的代码每次收到LiveData回调都会重新创建TasksListAdapter实例,再给RecyclerView重新设置adapter,相当于完全重置列表状态,所以会自动滚动到顶部,同时还会全量重绘所有item,性能也较差。你后续优化复用Adapter的逻辑已经解决了这个问题。
2. 首次打开偶尔列表为空的原因
你更新了Adapter内部的taskList数据集后,没有调用RecyclerView.Adapter的数据集变更通知方法,RecyclerView不知道数据已经更新,就不会触发列表重绘,因此会一直显示初始的空列表,直到下次主动刷新。
修正方案
方案1:使用DiffUtil差分刷新(推荐,性能最优)
仅需修改Adapter的taskList setter逻辑,自动计算数据变化、只刷新改动的条目,不会触发整体滚动,性能远高于全量刷新:
private inner class TasksListAdapter(): RecyclerView.Adapter<TaskHolder>(){ var taskList: List<TasksItemHolder> = emptyList() set(value){ val diffResult = DiffUtil.calculateDiff(object : DiffUtil.Callback() { override fun getOldListSize() = field.size override fun getNewListSize() = value.size // 用唯一ID判断是否为同一个条目 override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return field[oldItemPosition].id == value[newItemPosition].id } // 判断条目内容是否发生变化 override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { return field[oldItemPosition] == value[newItemPosition] } }) field = value diffResult.dispatchUpdatesTo(this) } // 原有逻辑保持不变 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TaskHolder { val view = layoutInflater.inflate(R.layout.tasks_list_item, parent, false) return TaskHolder(view) } override fun onBindViewHolder(holder: TaskHolder, position: Int) { holder.bind(taskList[position]) } override fun getItemCount() = taskList.size }
方案2:全量刷新(适合小数据量列表,实现简单)
如果你的列表数据量很小,也可以直接在数据集更新后调用全量通知:
private inner class TasksListAdapter(): RecyclerView.Adapter<TaskHolder>(){ var taskList: List<TasksItemHolder> = mutableListOf() set(value){ field = value notifyDataSetChanged() } // 剩余逻辑保持不变 }
冗余逻辑清理
可以删除onCreate里的Adapter初始赋值逻辑,避免重复赋值,LiveData返回数据后会自动更新列表:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) taskAdapter = TasksListAdapter() date = arguments?.getString(DATE_KEY) as String taskListViewModel.loadDate(date) }
修改完成后,两个问题都会解决:点击CheckBox仅会刷新对应条目,滚动位置不会变动,首次进入应用也不会出现列表空白的情况。
内容的提问来源于stack exchange,提问作者Nima Khajehpour
相关产品推荐
相关产品推荐

