Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DiffCallback not called in listadapter

Hi i'm trying to use listadapter and diffcallback in my app. Somehow the view not update at all, when i do something.

When i put some log inside my "areItemsTheSame" and "areContentsTheSame" inside callback, it's not called at all.

Here is my mainActivity

class MainActivity : AppCompatActivity() {

private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: TodoAdapter
private lateinit var viewManager: RecyclerView.LayoutManager

private lateinit var viewModel : TodoViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)

    //viewModel
    viewModel = ViewModelProviders.of(this).get(TodoViewModel::class.java)
    viewManager = LinearLayoutManager(this)
    viewAdapter = TodoAdapter(viewModel.todos)

    binding.btnNew.setOnClickListener {
        viewModel.todos.value!!.add(Todo(3, binding.newText.text.toString()))
    }

    recyclerView = binding.myRecyclerView

    recyclerView.apply {
        layoutManager = viewManager
        adapter = viewAdapter
    }

    viewModel.todos.observe(this, Observer{ list ->
        viewAdapter.submitList(list)
        Log.i("debug", "im @observe " + list.toString())
    })

}

}

and here is my Adapter

 class TodoAdapter(var items: MutableLiveData<ArrayList<Todo>>):
    ListAdapter<Todo, TodoAdapter.MyViewHolder>(TodoDiffCallback()) {

// Create new views (invoked by the layout manager)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
    // create a new view
    val inflater = LayoutInflater.from(parent.context)
    val binding  = ListItemBinding.inflate(inflater)

    return MyViewHolder(binding)
}


override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.todoText.text = getItem(position).task

    //delete
    holder.delBtn.setOnClickListener {
        items.value!!.removeAt(position)
        submitList(items.value)
        Log.i("debug", "@adapter what is items " + items.value.toString())
    }

//override fun getItemCount() = items.value!!.size


class MyViewHolder(val binding: ListItemBinding) : RecyclerView.ViewHolder(binding.root) {
    val todoText = binding.todoItem
    val delBtn = binding.btnDelete
    val ediBtn = binding.btnEdit
}

}

class TodoDiffCallback : DiffUtil.ItemCallback<Todo>(){

override fun areItemsTheSame(p0: Todo, p1: Todo): Boolean {
    Log.i("debug", " here " +p0 + " inItems " + p1 )
    return p0 == p1
}

override fun areContentsTheSame(p0: Todo, p1: Todo): Boolean {
    Log.i("debug", "here " + p0 + " inContents" + p1 )
    return p0.equals(p1)
}

}

my ViewModel

class TodoViewModel: ViewModel() {

val todos = MutableLiveData<ArrayList<Todo>>()

init{
    todos.value = arrayListOf(
        Todo(1, "cooking"),
        Todo(2, "washing")
    )
}

}

Unfortunately the android docs didn't give more examples on this.

Again, both "logs" inside my DiffUtil class not called at all. When i click remove button, the UI not updated but the log show the correct results.

thanks

like image 814
MisterCat Avatar asked Apr 23 '26 20:04

MisterCat


1 Answers

Current working solution

I read about the "observe in liveData", it doesn't triggered until i call "setValue" method.

So i add some new methods in my ViewModel class, where i apply the setValue example on adding newItem

fun addTodo(text: String) {
    _todos.value!!.add(Todo(3, text))
    _todos.setValue(_todos.value)
}

So far it works. I now only run submitList once, in my observe in MainActivity

   viewModel.todos.observe(this, Observer{ list ->
        viewAdapter.submitList(list.toMutableList())
    })

I still have a problem, which the "position" of the items, still somehow not right. Example:

  1. when i remove all items, the app crashes
  2. after i remove item from 2nd position (array[1]) and then i remove the new added task, it will give "error index out of bound "

So the "position" in onBindViewHolder, haven't changed after delete/or do other things [updated] (Problem solved by using: holder.getAdapterPosition())

like image 184
MisterCat Avatar answered Apr 25 '26 10:04

MisterCat