[英]RecyclerView and DiffUtil - A Concurrency Nightmare
DiffUtil
的文檔建議在后台線程上生成DiffUtil.DiffResult
,因為可能DiffUtil.DiffResult
很長的計算時間。 這對我來說似乎是一個壞主意,因為該線程可能在以下情況下運行在陳舊數據上(假設list
訪問是線程安全的):
list
並通知適配器 newList
替換list
,這將有一些添加和一些刪除的差異 DiffUtil.calculateDiff
背景並獲得DiffResult
的list
和newList
,並發布消息到主線程將使用newList
並調用DiffResult.dispatchUpdatesTo
list
newList
被設置為新數據源並且運行DiffResult.dispatchUpdatesTo
導致基礎數據的不一致視圖+自DiffResults
計算以來任何突變的DiffResults
嗯,這不好,所以讓我們從第3步開始改變:
newList
設置為新數據源,在后台調用DiffUtil.calculateDiff
並獲取DiffResult
for list
和newList
,並將消息發布到將調用DiffResult.dispatchUpdatesTo
的主線程 newList
突變的主線程采取操作,並通知適配器,導致數據視圖不一致,因為尚未調用DiffResult.dispatchUpdatesTo
對此有更多的變化,但沒有一個是好的。 似乎將DiffUtil
與大型數據集和變更集可靠地使用的唯一方法是在調用DiffResult.dispatchUpdatesTo
之前禁用或排隊所有更新。
我錯過了會導致上述錯誤的內容嗎?
看一下BatchingListUpdateCallback。 它是類,包含主回調,當列表發生多變化時,batchingListCallback只會在主回調時通知一次。
https://developer.android.com/reference/android/support/v7/util/BatchingListUpdateCallback.html
編輯
對不起,我的答案不正確。
我查看了源代碼DiffUtil。 而且我看到,BatchingListUpdateCallback無論如何都在dispatchUpdatesTo
方法中使用。
public void dispatchUpdatesTo(ListUpdateCallback updateCallback) {
final BatchingListUpdateCallback batchingCallback;
if (updateCallback instanceof BatchingListUpdateCallback) {
batchingCallback = (BatchingListUpdateCallback) updateCallback;
} else {
batchingCallback = new BatchingListUpdateCallback(updateCallback);
// replace updateCallback with a batching callback and override references to
// updateCallback so that we don't call it directly by mistake
//noinspection UnusedAssignment
updateCallback = batchingCallback;
}
但作為正確方式的矢量,這可能是有用的:)
我最終堆疊更新以管理DiffUtil計算期間的用戶交互,並且仍然只訪問主線程中的數據集。
我在那里寫了: https : //geoffreymetais.github.io/code/diffutil-threading/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.