The documentation for DiffUtil
sugeruje generowanie DiffUtil.DiffResult
na wątku tła ze względu na potencjalne długie czasy obliczeń. Wydaje się to zły pomysł do mnie, ponieważ nitka mogła działać na danych nieaktualnych w sytuacji takiej jak następuje (zakładając list
dostępu jest bezpieczne dla wątków):RecyclerView and DiffUtil - koszmar współbieżności
- Dodawanie danych do
list
i powiadomić adapterowi - Need zastąpić
list
znewList
miałoby diff z pewnymi dodatkami, a niektóre przeprowadzki - połączeń
DiffUtil.calculateDiff
w tle i uzyskaćDiffResult
dlalist
inewList
i wysyłać wiadomości do głównego wątku, który będzie używałnewList
i zadzwonićDiffResult.dispatchUpdatesTo
- Przed że wiadomość jest obsługiwana, użytkownik wykonuje czynność na głównym wątku, który powoduje mutacje
list
- wiadomości jest obsługiwany,
newList
jest ustawiona jako nowe źródło danych iDiffResult.dispatchUpdatesTo
jest uruchamiany powodując niespójne widok dane źródłowe + utrata wszelkich mutacji, ponieważDiffResults
obliczono
dobrze, że nie jest dobrze, więc zmieńmy zaczynając od kroku 3:
- Zestaw
newList
jako nowe źródło danych, nazywamyDiffUtil.calculateDiff
w tle i uzyskaćDiffResult
dlalist
inewList
i wysyłać wiadomości do głównego wątku, który będzie zadzwonićDiffResult.dispatchUpdatesTo
- Przed że wiadomość jest obsługiwana, użytkownik wykonuje czynność na głównym wątek, który powoduje mutacje
newList
i powiadamia zasilacza, co powoduje niespójność widok danych, ponieważDiffResult.dispatchUpdatesTo
nie został jeszcze
nazywany jest więcej wariacje na ten temat, ale nie są dobre. Wydaje się, że jedynym sposobem na niezawodne użycie DiffUtil
z dużym zestawem danych i zestaw zmian jest wyłączenie lub kolejkowanie wszystkich aktualizacji do czasu wywołania DiffResult.dispatchUpdatesTo
.
Czy brakuje mi czegoś, co sprawiłoby, że powyższe byłoby fałszywe?
przede wszystkim, ile przedmiotów masz? jeśli to nie kilka tysięcy, dlaczego się martwić? – pskink
@pskink jak dokumentacja stwierdza: '1000 pozycji i 200 modyfikacji bez ruchów: 13.54 ms, mediana: 13.36 ms'. 1000 przedmiotów to niewiele. Biorąc 13,54 ms, aby to zrobić, pozostawiamy nam 2,5 ms, aby wykonać wszystkie pozostałe prace dla tej ramki, lub będziemy mieli opuszczoną ramkę. 2,5 ms to mało czasu. – Eliezer
ok, więc użyj 'dispatchUpdatesTo (ListUpdateCallback updateCallback)', a nie 'dispatchUpdatesTo (Adapter adapter)', w ten sposób będziesz kontrolować sposób obsługi aktualizacji (możesz pominąć aktualizacje elementów, które zostały zmienione przez użytkownika w międzyczasie) – pskink