I'm using Android Room
and Rx Flowable
to update a RecyclerView
will the object from my database. For better animation and performance, I updated the project to use the new ListAdapter in my project.
The problem is when user presses a Checkbox
the Task object is updated as completed, the database reflects this change, but sometimes the adapter ListAdapter
notifies my onBindViewHolder
and sometimes it says that my view is already updated.
TaskListFragment
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
viewModel.loadTasks(onTasksLoaded = { adapter.submitList(it) })
}
TaskDao
@Query("SELECT * FROM task")
fun getAllTasks(): Flowable<MutableList<Task>>
TaskListAdapter
class TaskListAdapter : ListAdapter<Task, BindingHolder<*>>(TaskDiffCallback()) {
override fun onBindViewHolder(holder: BindingHolder<*>, position: Int) {
val task = getItem(position)
// more binding code
// THE ISSUE IS HERE
if (task.completed) {
holder.viewStrike.visibility = View.VISIBLE
} else {
holder.viewStrike.visibility = View.INVISIBLE
}
}
// more adapter code
}
Task
data class Task(
@ColumnInfo(name = "task_is_completed") var completed: Boolean = false,
@ColumnInfo(name = "task_description") var description: String,
@ColumnInfo(name = "task_category_id") var categoryId: Long? = null,
@ColumnInfo(name = "task_due_date") var dueDate: Calendar? = null
) : Parcelable {
@IgnoredOnParcel
@ColumnInfo(name = "task_id")
@PrimaryKey(autoGenerate = true)
var id: Long = 0
}
DiffUtil
class TaskDiffCallback : DiffUtil.ItemCallback<Task>() {
override fun areItemsTheSame(oldItem: Task, newItem: Task) =
oldItem.id == newItem.id
override fun areContentsTheSame(oldItem: Task, newItem: Task) =
oldItem.task == newItem.task
}
Debugging the app, sometimes the isCompleted
field updates correctly and sometimes the field is already updated during the Diff, so it says that the view has no updates. I couldn't find any pattern to this issue. In my case, sometimes the view holder.viewStrike
changes its visibility and sometimes it remains in inconsistent state.
The issue seems related to the ListAdapter
itself which sometimes sends the oldItem
with the updated value, so there is no diff to be updated.
Am I missing any implementation?
AsyncListDiffer#submitList
evaluatesnewList == mList
, and If you just change an item, but not the (size) of the list, this statement is true and the update process is cancelled. But I didn't find a workaround yet. – Runofthemill