我正在尝试跟踪在 notifyDataSetChanged
在 recyclerview 上执行后的一组语句。但是当我调试我的应用程序时,调试器会在我的 notifyDataSetChanged
之后到达几行代码,然后再进入recyclerview的适配器的 onBindViewHolder
。因此,我的问题是:notifyDataSetChanged 是异步调用吗?如果是,我们是否会得到回调?
PS:我已经搜索了这个答案,但是找不到合适的答案,所以我向社区寻求帮助。
我正在尝试跟踪在 notifyDataSetChanged
在 recyclerview 上执行后的一组语句。但是当我调试我的应用程序时,调试器会在我的 notifyDataSetChanged
之后到达几行代码,然后再进入recyclerview的适配器的 onBindViewHolder
。因此,我的问题是:notifyDataSetChanged 是异步调用吗?如果是,我们是否会得到回调?
PS:我已经搜索了这个答案,但是找不到合适的答案,所以我向社区寻求帮助。
我是RecyclerView的作者,
当你调用notifyDataSetChanged
时,RecyclerView会使数据失效,但直到下一帧动画才会更新UI。这就是android视图系统的工作方式。当小部件无效(例如更改其数据)时,它会请求布局,这意味着它将在下一个视图遍历中重新测量和重新布局。这样做是为了将所有更改批处理,直到下一次屏幕更新为止。这就是为什么notifyDataSetChanged
不会立即触发onBind
的原因。
所以是的,你可以将这称为异步调用,但这并不意味着你可以在多线程上运行它(这两个概念完全不同)。你仍然必须在主线程上对适配器进行所有更改。当你更改适配器时,你必须立即通知RecyclerView,这就是为什么通知也必须在主线程上的原因。
这种限制的原因是,如果在布局过程中更改了数据集,那么对于布局管理器来恢复到稳定状态非常困难(例如想象RecyclerView在同时调用onBind(5)
和另一个线程删除第5个项)。此外,考虑这些更改将需要大量的同步,这将是一个巨大的性能惩罚而没有任何好处。这就是为什么所有UI组件都是单线程的原因。
notify*
是异步的,这是否意味着相对于 scrollToPosition
它发生的顺序也是不确定的?我目前遇到了一些奇怪的问题,似乎表明存在竞态条件... http://stackoverflow.com/questions/39868846/recyclerview-race-condition-between-notify-and-scrolltopostion - david.miholanotifyDatasetChanged()
,如此处所示,该方法会更改UI,这些更改只能在主线程上完成。这使得调用同步。requestFocus()
一样。由于视图被重绘,因为数据集期望发生更改,它必须在主UI线程上进行(只有主循环程序(即UI线程)才能修改视图)。当使用此方法时,RecyclerView将尝试为报告具有稳定ID的适配器合成可见的结构更改事件。这可以帮助进行动画和视觉对象持久性,但是仍然需要重新绑定和重新布局单个项目视图。
默认观察器会认为所有数据都已更改,因为从Recycler view源代码中可以看出。
此事件未指定数据集发生了什么更改,因此强制所有观察者假定所有现有项和结构可能不再有效。LayoutManager将被强制完全重新绑定并重新布局所有可见视图。
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()){
@Override
public void onLayoutCompleted (RecyclerView.State state){
super.onLayoutCompleted(state);
// update UI for new layout
}
});
notifyDatasetChanged()
,该方法会在主线程上进行更改。因此它不能是异步的。 - Droidekas