这里我有一个由Room
和LiveData
填充的RecyclerView
。在RecyclerView
的每个项目中,我都有一个CheckBox
,它应该更新数据库行中的布尔值。所以问题是,当Database
更新时,RecyclerVie
将不得不再次绘制每个项目,所以滚动将在顶部。问题是如何在数据更新后恢复滚动。
代码如下:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_tasks_list, container, false)
recyclerView = view.findViewById(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(context)
fab = view.findViewById(R.id.fab_add_task_time) as FloatingActionButton
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
taskListViewModel.tasksListLiveData.observe(viewLifecycleOwner, Observer {
it?.let { taskList->
taskListViewModel.tasksList = taskList
this.recyclerView.adapter = TasksListAdapter(taskList)
}
})
}
private inner class TaskHolder(view: View): RecyclerView.ViewHolder(view){
private lateinit var id: UUID
// the other views
private val isDone = view.findViewById<CheckBox>(R.id.tasks_done)
init {
isDone.setOnClickListener {
taskListViewModel.updateTask((it as CheckBox).isChecked, id)
}
}
fun bind(itemHolder: TasksItemHolder){
this.id = itemHolder.id
isDone.isChecked = itemHolder.done
}
}
private inner class TasksListAdapter(var taskList: List<TasksItemHolder>): RecyclerView.Adapter<TaskHolder>(){
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(): Int {
return taskList.size
}
编辑:
所以我尝试添加一个新的内部类,扩展滚动侦听器上的回收器视图,并将其设置为我的滚动侦听器上的回收器。但同样的问题触发,我不能恢复之前的滚动更新,因为滚动的最后状态是当所有的东西更新和滚动是在顶部。
任何帮助都是感激的,即使它不起作用。
EDIT2:根据两个朋友的建议,他们说不要每次观察实时数据时都创建适配器,我已经更改了代码,所以我有一个适配器,我可以在其中放置一个列表,它可以完美地工作,并在更新后保持滚动的位置。虽然另一个问题已经积累,那就是当我关闭应用程序并再次打开它时,有时列表是空的,我必须关闭并重新打开片段以查看列表。我没有得到任何关于回收器或适配器的错误,即使它打开空。这是经过改进的代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
taskAdapter = TasksListAdapter()
if (taskListViewModel.tasksList != null){
taskAdapter.taskList = taskListViewModel.tasksList!!
}
date = arguments?.getString(DATE_KEY) as String
taskListViewModel.loadDate(date)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_tasks_list, container, false)
recyclerView = view.findViewById(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.adapter = taskAdapter
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
taskListViewModel.tasksListLiveData.observe(viewLifecycleOwner, Observer {
it?.let { taskList->
if (taskListViewModel.tasksList != taskList) {
taskListViewModel.tasksList = taskList
this.taskAdapter.taskList = taskListViewModel.tasksList!!
}
}
})
}
private inner class TaskHolder(view: View): RecyclerView.ViewHolder(view), View.OnClickListener{
private lateinit var taskId: UUID
private val taskIsDone = view.findViewById<CheckBox>(R.id.tasks_done)
init {
taskIsDone.setOnClickListener {
taskListViewModel.updateTask((it as CheckBox).isChecked, taskId)
}
}
fun bind(itemHolder: TasksItemHolder){
this.taskId = itemHolder.id
taskIsDone.isChecked = itemHolder.done
}
}
private inner class TasksListAdapter(): RecyclerView.Adapter<TaskHolder>(){
var taskList: List<TasksItemHolder> = mutableListOf()
set(value){field = value}
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(): Int {
return taskList.size
}
再次感谢@ michael和@ChhatrasalSinghBundela
所以显然我必须通知更改,它现在工作完美:)
这是因为每次数据更新时都重新创建适配器。看一下ListAdapter
这是Adapter的子类,它有submitList(List)
来更新结果。在那里有一个例子,如何创建适配器一次,并推动taskList
每次它的变化。