ViewHolder (ang. ViewHolder) (wzorzec kreacyjny) ma za zadanie zoptymalizować proces renderowania widoku kolekcji elementów poprzez ponowne użycie obiektów istniejących widoków. W trakcie przewijania listy dla każdego elementu kolekcji wywoływana jest kosztowna operacja wiązania widoku findViewById. W efekcie wzrasta zużycie zasobów, powstaje więcej obiektów widoku niż to w danej chwili potrzebne, a także przewijanie listy nie jest płynne. ViewHolder likwiduje wspomniane problemy. Przechowuje referencję do związanych instancji widoku w postaci obiektu typu ViewHolder i w razie potrzeby udostępnia je do ponownego użycia. Ilość stworzonych obiektów ViewHolder jest zależna od wielkości ekranu urządzenia i wynosi mniej więcej tyle ile maksymalnie może zostać wyświetlonych elementów w widoku (naraz bez przewijania).
Ograniczenia
Wykorzystanie wzorca ViewHolder nieznacznie zwiększa poziom skomplikowania.
Użycie
Wzorzec używany jest w widokach kolekcji w celu optymalizacji zużycia zasobów pamięci urządzenia. Dla niewielkich kolekcji (mieszczących się w całości na ekranie) różnica w wydajności może nie występować lub być niezauważalna, jednakże gdy nie mieszczą się one na ekranie i możliwe jest przewinięcie listy wówczas skok wydajności jest zauważalnym gołym okiem.
Implementacja
Wewnętrzna klasa ViewHolder przechowuje referencję do obiektów widoku View. Referencje są ustawiane w klasie adaptera bezpośrednio na obiekcie viewholder lub przekazywany jest cały widok do konstruktora ViewHolder, który sam dba o związanie obiektów widoku. Klasa Adapter wykorzystuje obiekt typu ViewHolder do pobrania referencji i przekazania danych do widoków.
W celu uproszczenia idei wzorca ViewHolder przedstawiona poniżej implementacja dedykowania jest dla widoku kolekcji typu ListView oraz klasy adaptera rozszerzającego BaseAdapter. Jednakże zalecane jest wykorzystanie widoku kolekcji RecyclerView wraz implementacją klasy rozszerzającej RecyclerView.Adapter.
Aktywność lub fragment tworzą tworzą widok listy do którego przekazany jest adapter z danymi kolekcji wykorzystujący ViewHolder.
Przykład
Aplikacja FoodDeliver umożliwia użytkownikom dokonanie zamówienia dostawy jedzenia z wybranej restauracji. Wiele widoków aplikacji (w tym widok pozycji menu z danej restauracji) wykorzystuje mechanizm widoku przewijalnej listy. W celu optymalizacji wydajności działania listy do realizacji tego zadania użyto kontrolkę RecyclerView wraz z implementacją ViewHolder.
Aktywność lub fragment pobierają dane z serwera o dostępnych pozycjach menu. Następnie tworzony jest adapter, który jest przekazywany do widoku kolekcji RecyclerView.
Biblioteki
Użycie widoku typu RecyclerView wymusza na programiście implementację wewnętrznej klasy RecyclerView.ViewHolder. Realizacja wzorca w starszych widokach kolekcji np.: ListView, GridView jest opcjonalna.