To trudna sytuacja, przepraszam, że dokumenty nie są wystarczające.
Gdy zmienia się zawartość adaptera (i wywołujesz notify***()
), RecyclerView żąda nowego układu. Od tego momentu, dopóki system układu nie zdecyduje się obliczyć nowego układu (<16 ms), położenie układu i położenie adaptera mogą nie pasować, ponieważ układ nie odzwierciedla jeszcze zmian adaptera.
W twoim przypadku, ponieważ twoje dane są powiązane z zawartością twojego adaptera (i zakładam, że dane są zmieniane w tym samym czasie ze zmianami adaptera), powinieneś używać adapterPosition
.
Uważaj jednak, jeśli dzwonisz notifyDataSetChanged()
, ponieważ unieważnia to wszystko, RecyclerView nie wie, że pozycja adaptera ViewHolder do czasu obliczenia następnego układu. W takim przypadku getAdapterPosition()
zwróci RecyclerView#NO_POSITION
( -1
).
Ale powiedzmy, że jeśli zadzwoniłeś notifyItemInserted(0)
, getAdapterPosition()
ViewHolder, który był poprzednio na pozycji 0
, zacznie 1
natychmiast wracać . Tak długo, jak wysyłasz szczegółowe zdarzenia powiadomień, zawsze jesteś w dobrym stanie (znamy położenie adaptera, mimo że nowy układ nie został jeszcze obliczony).
Inny przykład, jeśli robisz coś po kliknięciu przez użytkownika, jeśli getAdapterPosition()
zwraca NO_POSITION
, najlepiej zignorować to kliknięcie, ponieważ nie wiesz, co kliknął użytkownik (chyba że masz inny mechanizm, np. Stabilne identyfikatory do wyszukiwania pozycji).
Edytuj, gdy pozycja układu jest dobra
Powiedzmy, że używasz LinearLayoutManager
i chcesz uzyskać dostęp do ViewHolder nad aktualnie klikniętym elementem. W takim przypadku powinieneś użyć pozycji układu, aby uzyskać powyższy element.
mRecyclerView.findViewHolderForLayoutPosition(myViewHolder.getLayoutPosition() - 1)
Musisz użyć pozycji układu, ponieważ pasuje ona do tego, co użytkownik obecnie widzi na ekranie.
By wykazać różnice (S)
getAdapterPosition()
,getLayoutPosition()
i równieżposition
; zwrócilibyśmy uwagę na poniższe przypadki:1.
position
argument wonBindViewHolder()
metodzie:Możemy użyć
position
do powiązania danych z widokiem i jest w porządku użycieposition
argumentu, aby to zrobić, ale nie jest w porządku używanieposition
argumentu do obsługi kliknięć użytkownika, a jeśli go użyłeś, zobaczysz ostrzeżenie "Nie traktowaćposition
jako naprawione i użyjholder.getAdapterPosition()
zamiast tego ".2
getAdapterPosition()
.:Ta metoda zawsze obejmuje zaktualizowaną pozycję adaptera
holder
. Oznacza to, że za każdym razem, gdy klikasz na element, pytasz adapter o toposition
. dzięki czemu uzyskasz najnowszą pozycję tego elementu pod względem logiki adaptera.3
getLayoutPosition()
.:Czasami konieczne jest znalezienie
position
pod względem zaktualizowanego układu (ostatnio przekazanego układu, który użytkownik widzi teraz), na przykład: Jeśli użytkownik poprosi o trzeciposition
, może zobaczyć i używaszswipe
/dismiss
dla przedmiotów lub zastosuj dowolną animację lub dekoracje dla przedmiotów, które lepiej będzie użyćgetLayoutPosition()
zamiastgetAdapterPosition()
, ponieważ zawsze będziesz mieć pewność, że masz do czynienia z pozycją przedmiotów pod względem ostatnio przekazanego układu.Aby uzyskać więcej informacji na ten temat; zobacz tutaj . . .
źródło