Jest to trudna sytuacja, przepraszam, że dokumenty nie są wystarczające.
Po zmianie zawartości adaptera (i wywołanie notify***()
) RecyclerView żąda nowego układu. Od tego momentu, aż układ układu zdecyduje się na obliczenie nowego układu (< 16 ms), pozycja układu i położenie adaptera mogą nie być zgodne, ponieważ układ nie odzwierciedlił jeszcze zmian adaptera.
W twoim przypadku użycia, ponieważ twoje dane są powiązane z twoją zawartością adaptera (i zakładam, że dane są zmieniane w tym samym czasie ze zmianami adaptera), powinieneś używać adapterPosition
.
Bądź jednak ostrożny, jeśli dzwonisz pod numer notifyDataSetChanged()
, ponieważ powoduje on unieważnienie wszystkiego, RecyclerView nie wie, że pozycja adaptera ViewHolder jest obliczana, dopóki nie zostanie obliczony następny układ. W takim przypadku getAdapterPosition()
zwróci RecyclerView#NO_POSITION
(-1
).
Ale powiedzmy, że jeśli już nazywany notifyItemInserted(0)
The getAdapterPosition()
z ViewHolder który był poprzednio w pozycji 0
rozpocznie powrocie 1
natychmiast. Tak długo, jak wysyłasz szczegółowe powiadomienia o zdarzeniach, zawsze jesteś w dobrym stanie (znamy pozycję adaptera, mimo że nowy układ nie jest jeszcze obliczany).
Inny przykład, jeśli robisz coś na kliknięciu przez użytkownika, jeśli getAdapterPosition()
powraca NO_POSITION
, najlepiej jest ignorować tego kliknięcia, bo nie wiem, co użytkownik kliknął (chyba że masz jakiś inny mechanizm, np stabilne identyfikatory do wyszukiwania przedmiot).
Edit Dla Kiedy Układ Pozycja jest dobry
Powiedzmy używasz LinearLayoutManager
i chcesz uzyskać dostęp do ViewHolder powyżej aktualnie klikniętego elementu. 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ż odpowiada to, co użytkownik aktualnie widzi na ekranie.
Grałem trochę i okazało się, że metoda getAdapterPosition() zawsze zwraca -1 na mnie. Debugowałem go i powodem jest to, że kod w metodzie (ostateczny rodzic ViewParent = itemView.getParent(); if (! (Nadrzędny egzemplarz RecyclerView)) {return -1;} zawsze dostaje się do bloku if, tj. Widok recyklera nie jest rodzicem widoku mojej komórki.Jak to może być? Mój kod do utworzenia posiadacza to: return MyViewHolder (LayoutInflater.from (viewGroup.getContext()). inflate (R.layout.test_list_item, viewGroup, false)); (Ciąg dalszy w innym komentarzu.) – wujek
Kiedy zmieniam kod, aby zadzwonić nadmuchać (R.layout.test_list_item, ViewGroup, true); (zwróć uwagę na polecenie "dołącz do root'a"), Android rzuca: java.lang.IllegalStateException: Określone dziecko ma już rodzica. Najpierw musisz wywołać metodę removeView() na rodzicu dziecka. Jaki jest więc właściwy sposób utworzenia widoku z widokiem prawidłowo połączonym z widokiem recyklera? O dziwo, nawet jeśli getAdapterPosition() zwraca -1, ponieważ rodzic jest zerowy, wszystko inne działa poprawnie. – wujek
Parametr boolowski w inflatorze układu to "addToParent". Musi być fałszywe, ponieważ to LayoutManager ma obowiązek go dodać. Myślę, że wywołujecie getAdapterPosition w onBind, gdzie już minęło pozycję. Z technicznego punktu widzenia właściciel widoku reprezentuje tę pozycję po powrocie onBind. Przy okazji zaktualizowaliśmy pozycję getAdapter, aby zwrócić prawidłową pozycję (jeśli to możliwe), nawet jeśli jest ona odłączona, wkrótce zostanie udostępniona. – yigit