MisterCat
MisterCat

Reputation: 1631

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

Upvotes: 3

Views: 4714

Answers (1)

MisterCat
MisterCat

Reputation: 1631

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())

Upvotes: 1

Related Questions