【问题标题】:Which is more expensive, notifyDatasetChanged() or looping over a large cursor?哪个更昂贵,notifyDatasetChanged() 还是在大游标上循环?
【发布时间】:2016-03-02 23:27:49
【问题描述】:

基本上,我有一个带有适配器的 RecyclerView,它从游标填充数据。我有两个选项来获取项目动画:

  1. 使用setHasStableIds(true) 并覆盖getItemId 以返回数据库行的ID,然后在适配器中使用swapCursor 函数将其当前游标与新游标交换,然后调用notifyDatasetChanged

  2. 类似于选项 1,但不是简单地交换游标并调用 notifyDatasetChanged,而是遍历旧游标和新游标,比较行以确定哪些行已添加/删除/更改并跟踪它们,然后调用notifyItemAddednotifyItemChanged 等来具体告诉适配器更新了什么

使用选项 1,notifyDatasetChanged 将重新绑定所有效率低下的可见项目(和其他一些东西),但使用选项 2,我将不得不遍历完整光标以确定已添加哪些项目/删除,如果光标相当大,这也可能需要一些时间。有没有人知道哪个是更好的解决方案以及为什么?

编辑:

为了让事情更有趣,我还有第三种选择:

  1. 与选项 2 类似,但不是遍历游标中的每个项目,而是仅遍历当前绑定的项目(通过检查 RecyclerView 的子项来确定),因为其他项将在以下情况下获取新的游标值他们被束缚了。唯一的问题是它不适用于添加/删除,因此如果oldCursor.count() != newCursor.count(),解决方法是进行完整迭代。如果计数相同,我可以执行setHasStableIds(false),然后即使某个位置的行与以前不同,onBindViewHolder 也会处理它。

这样做的缺点是 ID 不稳定,这意味着 RecyclerView 将不得不在某些地方做一些额外的工作

【问题讨论】:

    标签: android performance cursor android-recyclerview adapter


    【解决方案1】:

    选项 2 容易出错。我会选择选项 1,保持简单。

    【讨论】:

    • 我并不真正担心错误,我实际上已经为这两个选项编写了代码,并且它们都可以正常工作(以及新选项 3 的大部分代码),只是尝试找出哪个最有效
    • 然后只需添加一些指标,您就可以使用 System.nanotime() 并获取时间样本来测量您的循环需要多长时间以及适配器交换光标和刷新内容需要多长时间。或者使用 traceView 获取一些指标。
    猜你喜欢
    • 2017-06-09
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 2020-07-25
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多