【问题标题】:DiffCallback not called in listadapter未在 listadapter 中调用 DiffCallback
【发布时间】:2019-10-04 08:28:58
【问题描述】:

您好,我正在尝试在我的应用程序中使用 listadapter 和 diffcallback。不知何故,当我做某事时,视图根本不会更新。

当我在回调中的“areItemsTheSame”和“areContentsTheSame”中放入一些日志时,根本不会调用它。

这是我的主要活动

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

}

}

这是我的适配器

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

}

我的视图模型

class TodoViewModel: ViewModel() {

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

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

}

不幸的是,android 文档没有提供更多关于此的示例。

同样,我的 DiffUtil 类中的两个“日志”都没有被调用。当我单击删除按钮时,UI 未更新,但日志显示正确的结果。

谢谢

【问题讨论】:

  • 我可以看看你的视图模型吗?
  • 您确定您的列表确实在改变吗?
  • 我昨天和你有同样的问题。那是因为您使用的列表是视图模型中相同的索引引用,您可以尝试调试并检查适配器和实时数据视图模型中的列表我的解决方案但不是最好的方法是从实时数据复制数组并发布具有不同引用的新数组跨度>
  • @RofieSagara 我在上面添加了它,谢谢
  • 在初始设置后,您并没有真正改变 todos 的值。为什么会触发 diffutils?

标签: android kotlin android-recyclerview


【解决方案1】:

当前的工作解决方案

我读到了“在 liveData 中观察”,它在我调用“setValue”方法之前不会触发。

所以我在我的 ViewModel 类中添加了一些新方法,我在其中应用了 setValue 添加新项目的示例

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

到目前为止它有效。我现在只运行一次 submitList,在 MainActivity 中观察

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

我仍然有一个问题,其中项目的“位置”,仍然莫名其妙地不对。示例:

  1. 当我删除所有项目时,应用程序崩溃
  2. 在我从第二个位置(数组 [1])删除项目然后删除新添加的任务后,它会给出“错误索引超出范围”

所以 onBindViewHolder 中的“位置”,在删除/或做其他事情后没有改变 [更新](问题通过使用解决:holder.getAdapterPosition())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2015-07-06
    • 2018-09-18
    • 1970-01-01
    相关资源
    最近更新 更多