metody getViewTypeCount i getItemViewType klasy ArrayAdapter

159

Czy ktoś może prostymi słowami wyjaśnić mi zastosowanie getViewTypeCount()i getItemViewType()metody ArrayAdapter?

Eugene
źródło

Odpowiedzi:

308

Obsługują one przypadek, w którym potrzebujesz różnych typów widoków dla różnych wierszy. Na przykład w aplikacji do obsługi kontaktów możesz chcieć, aby parzyste wiersze miały obrazy po lewej stronie, a nieparzyste wiersze miały obrazy po prawej. W takim przypadku użyłbyś:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

Struktura używa Twojego typu widoku, aby zdecydować, które widoki przekazać convertVieww Twojej getViewmetodzie . Innymi słowy, w powyższym przykładzie wiersze parzyste otrzymają tylko widoki z recyklingu ze zdjęciami po lewej stronie do ponownego wykorzystania, a wiersze nieparzyste otrzymają tylko te ze zdjęciami po prawej stronie.

Jeśli każdy wiersz na liście ma ten sam układ, nie musisz się martwić o typy widoków. W rzeczywistości BaseAdapter.java zapewnia domyślne zachowanie dla wszystkich adapterów:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

To rzeczywiście zapewnia ten sam typ widoku dla każdego wiersza.

Edytuj - aby zarysować ogólny przepływ:

  1. Łączysz dane z własnym AdapterViewza pomocą adaptera.
  2. W AdapterViewpróbuje wyświetlić elementy, które są widoczne dla użytkownika.
  3. Struktura wywołuje getItemViewTypewiersz n, wiersz, który ma zostać wyświetlony.
  4. Struktura sprawdza pulę odtworzonych widoków pod kątem widoków typu wiersza n. Nie znajduje żadnego, ponieważ żadne widoki nie zostały jeszcze przetworzone.
  5. getViewjest wezwany do wiersza n.
  6. Wywołujesz getItemViewTypewiersz, naby określić, jakiego typu widoku należy użyć.
  7. Instrukcja if / switch służy do wypełniania innego pliku xml w zależności od wymaganego typu widoku.
  8. Wypełniasz widok informacjami.
  9. Wracasz do widoku, zamykasz getView, a widok Twojego wiersza jest wyświetlany użytkownikowi.

Teraz, gdy widok jest odtwarzany przez przewijanie ekranu, trafia do puli widoków odtworzonych, zarządzanej przez platformę. Są one zasadniczo uporządkowane według typu widoku, dzięki czemu w convertViewparametrze getViewmetody otrzymujesz widok odpowiedniego typu :

  1. Struktura ponownie wywołuje getItemViewTypewiersz, który chce wyświetlić.
  2. Tym razem jest widok w puli poddanej recyklingowi odpowiedniego typu.
  3. Widok z recyklingu jest przesyłany do Ciebie jako convertViewparametr do getViewmetody.
  4. Wypełniasz widok recyklingu nowymi informacjami i zwracasz go.
Matthew Willis
źródło
1
@Matthew, dziękuję za odpowiedź. Czy możesz opisać przepływ wywoływania tych metod. Nie rozumiem też, w jaki sposób jest to faktycznie powiązane z moimi danymi w res / layout.
Eugene
Nie ma jawnego kontraktu określającego, kiedy te metody są wywoływane. res / layout to miejsce do przeglądania obiektów. To jest adapter . Powinieneś sprawdzić typ elementu w swojej metodzie getView i odpowiednio nadmuchać właściwy widok z res / layout.
Matthew Willis,
1
Zwracasz go samemu w getItemViewType.
Matthew Willis
Skojarzenie wykonujesz ręcznie w getView: if (type == 0) {/ * inflate R.layout.row_icon_on_left /} else {/ inflate R.layout.row_icon_on_right * /}
Matthew Willis
75
Strzec się! getItemViewType () musi zwracać wartość int między 0 a getViewTypeCount () - 1.
PacificSky
12

Jeśli musimy pokazać inny typ widoku w widoku listy, to jest dobry w użyciu getViewTypeCount()i getItemViewType()w adapterze zamiast przełączania widoku View.GONEi View.VISIBLEmoże być bardzo kosztownym zadaniem, getView()które wpłynie na przewijanie listy.

Sprawdź, czy używasz adaptera getViewTypeCount()i getItemViewType()w nim.

Link: the-use-of-getviewtypecount

kyogs
źródło
Zwrócenie IGNORE_ITEM_VIEW_TYPE w getItemViewType () zawsze spowoduje przekazanie 'view' jako null w getView (pozycja int, widok View, ViewGroup viewGroup) wymuszając zainicjowanie wszystkich komponentów UI. Czy nie jest to zły wskaźnik wydajności, w którym w przypadku wzorca posiadacza możemy ponownie wykorzystać istniejące widoki interfejsu użytkownika i możemy po prostu przełączyć widok na View.GONE lub View.VISIBLE na podstawie pozycji.
Namrata Bagerwal
11

Oglądaj Outttt !!!!
Musiałem zmierzyć się z problemem z implementacją ListViewwczoraj i dwa rodzaje widoków wierszy pomieszały się zaraz po przewinięciu. Mimo, że najwyżej głosowana odpowiedź w tym wątku daje dobre ogólne wyjaśnienie, nie podkreśliła najważniejszej informacji, aby zatrzymać powyższy błąd interfejsu użytkownika, o którym wspomniałem.

Oto moje wyjaśnienie:
Obie getViewTypeCount()i getItemViewType()są wykorzystywane przez BaseAdapter„s getViewmetoda, aby dowiedzieć się, jaki rodzaj widoku należy pobrać, ekologiczny i wrócił. (jak wyjaśniono w pierwszej odpowiedzi w wątku). Ale jeśli nie zaimplementujesz tych dwóch metod intuicyjnie zgodnie z Android API Doc, możesz dostać się do problemu, o którym wspomniałem.

Podsumowanie wytycznych dotyczących implementacji:
Aby zaimplementować wiele typów wierszy Viewsfor ListView, musimy zasadniczo zaimplementować getItemViewType()i getViewTypeCount()metody. I getItemViewType()dokumentacja daje nam uwaga co następuje:

Uwaga: liczby całkowite muszą mieścić się w zakresie 0do getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEmożna również zwrócić.

Więc w swoim getItemViewType()powinieneś zwrócić wartości dla typu widoku, zaczynając od 0, do ostatniego typu as (liczba typów - 1). Na przykład, powiedzmy, że masz tylko trzy rodzaje widoków? Tak więc w zależności od obiektu danych dla widoku, można zwrócić tylko 0 lub 1 lub 2, od getItemViewType()sposobu, jak indeks tablicy zera. Ponieważ masz używane trzy typy widoków, Twoja getViewTypeCount()metoda musi zwracać 3.

W każdym razie, jeśli zwrócisz jakiekolwiek inne wartości całkowite, takie jak 1, 2, 3 lub 111, 222, 333 dla tej metody, na pewno możesz napotkać powyższy błąd interfejsu użytkownika, który właśnie umieściłeś, nie przestrzegając dokumentacji Android API.

Jeśli nie dostałeś wskazówki lub nadal nie możesz rozwiązać problemu i potrzebujesz dalszych informacji, przeczytaj moją szczegółową odpowiedź w tym wątku pytań i odpowiedzi StackOverflow .

Przeczytaj dokumentację dla programistów Androida, aby uzyskać więcej informacji, możesz znaleźć wskazówkę bezpośrednio.

Mam nadzieję, że ta odpowiedź może pomóc komuś zaoszczędzić wiele godzin !!!

Twoje zdrowie!!!

Randika Vishman
źródło
1
Dzięki za wspomnienie, IGNORE_ITEM_VIEW_TYPEże mam błąd w jednym z moich ListView. Użyłem ArrayAdapter, aby wstawić widok składający się z 1 obrazu i 2 widoku tekstu. Miałem tylko jeden typ widoku. Próbowałem albo nie zastąpić metody getItemViewType, albo zastąpić ją, zwracając pozycję lub zakodowaną na stałe liczbę całkowitą. We wszystkich przypadkach na mojej liście występowały duplikaty, z dziwnym zachowaniem podczas przewijania (duplikaty zmian). Powrót IGNORE_ITEM_VIEW_TYPEdo metody rozwiązał problem. Dzięki.
Alex
@Alex cieszy się, że było to dla Ciebie pomocne! :-)
Randika Vishman