2020 年 7 月更新:
谷歌为此添加了回调!请参阅:https://developer.android.com/reference/androidx/recyclerview/widget/AsyncListDiffer#submitList(java.util.List%3CT%3E,%20java.lang.Runnable)
以前的答案,来自糟糕的过去:
首先,我不敢相信谷歌没有为此提供回调。
我深入研究了 的源代码AsyncListDiffer
,发现当所有 RecyclerView 更新完成时,可以接收回调——但是接收这个回调的方式很奇怪。
您需要创建 的子类BatchingListUpdateCallback
,然后将您的ListUpdateCallback
(或AdapterListUpdateCallback
在大多数情况下)包装在其中。
然后,您应该覆盖dispatchLastEvent
. AsyncListDiffer
将调用它,但其中一个更新已被发送。在你的dispatchLastEvent
,你会想要调用超级实现,所以你不会破坏任何东西。您还需要调用自定义回调,这是您的方式。
在 Kotlin 中看起来像:
class OnDiffDoneListUpdateCallback(
listUpdateCallback: ListUpdateCallback,
private val onDiffDoneCallback: () -> Unit
) : BatchingListUpdateCallback(listUpdateCallback) {
override fun dispatchLastEvent() {
super.dispatchLastEvent()
onDiffDoneCallback()
}
}
最后一步是OnDiffDoneListUpdateCallback
向AsyncListDiffer
. 为此,您需要AsyncListDiffer
为自己初始化 - 如果您正在使用ListAdapter
或类似的东西,您需要重构以便您可以控制AsyncListDiffer
.
在 Kotlin 中,这看起来像:
private val asyncListDiffer = AsyncListDiffer<ItemType>(
OnDiffDoneListUpdateCallback(AdapterListUpdateCallback(adapter)) {
// here's your callback
doTheStuffAfterDiffIsDone()
},
AsyncDifferConfig.Builder<ItemType>(diffCallback).build()
)
编辑:当然,我忘记了边缘情况!
有时,dispatchLastEvent
不调用,因为AsyncListDiffer
认为更新微不足道。这是它所做的检查:
if (newList == mList) {
...
return;
}
// fast simple remove all
if (newList == null) {
...
mUpdateCallback.onRemoved(0, countRemoved);
return;
}
// fast simple first insert
if (mList == null) {
...
mUpdateCallback.onInserted(0, newList.size());
return;
}
我建议在你打电话之前自己做这些检查asyncListDiffer.submitList(list)
。但当然,这不可能那么容易!mList
是私有的,getCurrentList
如果为空,将返回一个空列表mList
,所以对这个检查没有用。相反,您必须使用反射来访问它:
val listField = AsyncListDiffer::class.java.getDeclaredField("mList")
listField.isAccessible = true
val asyncDifferList = listField.get(asyncListDiffer) as List<ItemType>?
asyncListDiffer.submitList(newList)
if(asyncDifferList == null) {
onDiffDone()
}
if(newList == null) {
onDiffDone()
}
if(newList == asyncDifferList) {
onDiffDone()
}
编辑 2:现在,我知道你在说什么 - 肯定有一种更简单、更简单的方法来做到这一点?答案是……是的!只需将整个AsyncListDiffer
类复制到您的项目中,然后自己添加回调!