Twórz dynamiczne listy za pomocą RecyclerView w ramach Androida Jetpack.

Wypróbuj sposób tworzenia wiadomości
Jetpack Compose to zalecany zestaw narzędzi UI na Androida. Dowiedz się, jak korzystać z układów w sekcji Utwórz

RecyclerView ułatwia efektywne wyświetlanie dużych zbiorów danych. Podajesz dane i określisz, jak wygląda każdy element, a biblioteka RecyclerView dynamicznie tworzy odpowiednie elementy, gdy są potrzebne.

Jak sama nazwa wskazuje, obiekt RecyclerView recycleruje te elementy. Gdy element przewija się poza ekran, RecyclerView nie usuwa jego widoku. Zamiast tego RecyclerView będzie używać tego widoku w przypadku nowych elementów, które zostały przewinięte na ekranie. RecyclerView zwiększa wydajność i responsywność aplikacji oraz zmniejsza zużycie energii.

Klasy kluczy

Dynamiczną listę można utworzyć razem z kilkoma klasami.

  • RecyclerView to ViewGroup, który zawiera widoki danych odpowiadające Twoim danym. To widok, więc dodajesz do układu element RecyclerView w taki sam sposób, w jaki dodajesz każdy inny element interfejsu.

  • Każdy element na liście jest definiowany przez obiekt viewlot. Po utworzeniu właściciela widoku nie będą z nim powiązane żadne dane. Po utworzeniu właściciela widoku danych RecyclerView powiąże go z jego danymi. Zakres właściciela widoku definiuje się, rozwijając komponent RecyclerView.ViewHolder.

  • RecyclerView prosi o wyświetlenia i wiąże widoki danych ze swoimi danymi, wywołując metody w adapterze. Aby zdefiniować adapter, wydłużaj wymiar RecyclerView.Adapter.

  • Menedżer układu porządkuje poszczególne elementy listy. Możesz użyć jednego z menedżerów układu dostępnych w bibliotece RecyclerView albo zdefiniować własny. Menedżerowie układu są oparte na klasie abstrakcyjnej LayoutManager biblioteki.

Sposób łączenia tych wszystkich elementów możesz zobaczyć w przykładowej aplikacji RecyclerView (Kotlin) lub przykładowej aplikacji RecyclerView (Java).

Etapy wdrażania RecyclerView

Jeśli zamierzasz używać RecyclerView, musisz wykonać kilka czynności. Szczegółowo opisujemy je w kolejnych sekcjach.

  1. Wybierz wygląd listy lub siatki. Zwykle można użyć jednego ze standardowych menedżerów układu biblioteki RecyclerView.

  2. Zaprojektuj wygląd i zachowanie każdego elementu na liście. Na podstawie tego projektu rozszerz klasę ViewHolder. Twoja wersja ViewHolder oferuje wszystkie funkcje związane z elementami list. Widok ten otacza element View, a widokiem tym zarządza RecyclerView.

  3. Określ Adapter, który wiąże Twoje dane z widokami ViewHolder.

Dostępne są też zaawansowane opcje dostosowywania, które pozwalają dostosować widok RecyclerView do swoich potrzeb.

Planowanie układu

Elementy w widoku RecyclerView są uporządkowane według klasy LayoutManager. Biblioteka RecyclerView zawiera 3 menedżery układu, które obsługują najczęstsze sytuacje związane z układami:

  • LinearLayoutManager umieszcza elementy na jednowymiarowej liście.
  • GridLayoutManager umieści elementy w dwuwymiarowej siatce:
    • Jeśli siatka jest ustawiona pionowo, GridLayoutManager stara się, by wszystkie elementy w każdym wierszu miały tę samą szerokość i wysokość, ale różne wiersze mogą mieć różne wysokości.
    • Jeśli siatka jest ustawiona poziomo, GridLayoutManager stara się, by wszystkie elementy w każdej kolumnie miały tę samą szerokość i wysokość, ale różne kolumny mogą mieć różną szerokość.
  • Kolumna StaggeredGridLayoutManager jest podobna do właściwości GridLayoutManager, ale nie wymaga, aby elementy w wierszu miały tę samą wysokość (w przypadku siatek pionowych) lub elementy w tej samej kolumnie miały tę samą szerokość (w przypadku siatek poziomych). W efekcie elementy w wierszu lub kolumnie mogą się znajdować w tym samym przesunięciu.

Musisz też zaplanować układ poszczególnych elementów. Będzie on potrzebny podczas projektowania uchwytu widoku, zgodnie z opisem w następnej sekcji.

Implementacja adaptera i uchwytu

Po określeniu układu musisz wdrożyć Adapter i ViewHolder. Te 2 klasy współdziałają, aby określić sposób wyświetlania danych. Element ViewHolder otacza element View, który zawiera układ poszczególnych elementów listy. Adapter w razie potrzeby tworzy obiekty ViewHolder i ustawia dane dla tych widoków. Proces kojarzenia widoków z ich danymi nazywa się powiązaniem.

Podczas definiowania adaptera musisz zastąpić 3 kluczowe metody:

  • onCreateViewHolder(): RecyclerView wywołuje tę metodę, gdy zachodzi potrzeba utworzenia nowego elementu ViewHolder. Ta metoda tworzy i inicjuje obiekt ViewHolder oraz powiązaną z nim View, ale nie wypełnia treści widoku – element ViewHolder nie został jeszcze powiązany z konkretnymi danymi.

  • onBindViewHolder(): RecyclerView wywołuje tę metodę, aby powiązać ViewHolder z danymi. Metoda pobiera odpowiednie dane i wykorzystuje je do wypełnienia układu właściciela widoku. Jeśli na przykład RecyclerView wyświetla listę nazw, metoda może znaleźć odpowiednią nazwę na liście i wypełnić widżet TextView osoby wyświetlania.

  • getItemCount(): RecyclerView wywołuje tę metodę, aby uzyskać rozmiar zbioru danych. Na przykład w aplikacji książki adresowej może być to łączna liczba adresów. RecyclerView korzysta z tej funkcji, aby określić, kiedy nie ma więcej elementów, które można wyświetlić.

Oto typowy przykład prostego adaptera z zagnieżdżonym elementem ViewHolder, który wyświetla listę danych. W tym przypadku RecyclerView wyświetla prostą listę elementów tekstowych. Adapter jest przekazywany w tablicy ciągów tekstowych zawierających tekst elementów ViewHolder.

Kotlin


class CustomAdapter(private val dataSet: Array<String>) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView

        init {
            // Define click listener for the ViewHolder's View
            textView = view.findViewById(R.id.textView)
        }
    }

    // Create new views (invoked by the layout manager)
    override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
        // Create a new view, which defines the UI of the list item
        val view = LayoutInflater.from(viewGroup.context)
                .inflate(R.layout.text_row_item, viewGroup, false)

        return ViewHolder(view)
    }

    // Replace the contents of a view (invoked by the layout manager)
    override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.textView.text = dataSet[position]
    }

    // Return the size of your dataset (invoked by the layout manager)
    override fun getItemCount() = dataSet.size

}

Java


public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private String[] localDataSet;

    /**
     * Provide a reference to the type of views that you are using
     * (custom ViewHolder)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder {
        private final TextView textView;

        public ViewHolder(View view) {
            super(view);
            // Define click listener for the ViewHolder's View

            textView = (TextView) view.findViewById(R.id.textView);
        }

        public TextView getTextView() {
            return textView;
        }
    }

    /**
     * Initialize the dataset of the Adapter
     *
     * @param dataSet String[] containing the data to populate views to be used
     * by RecyclerView
     */
    public CustomAdapter(String[] dataSet) {
        localDataSet = dataSet;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        // Create a new view, which defines the UI of the list item
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.text_row_item, viewGroup, false);

        return new ViewHolder(view);
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder viewHolder, final int position) {

        // Get element from your dataset at this position and replace the
        // contents of the view with that element
        viewHolder.getTextView().setText(localDataSet[position]);
    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return localDataSet.length;
    }
}

Układ każdego elementu widoku jest zdefiniowany w pliku układu XML w zwykły sposób. W tym przypadku aplikacja ma plik text_row_item.xml podobny do tego:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/list_item_height"
    android:layout_marginLeft="@dimen/margin_medium"
    android:layout_marginRight="@dimen/margin_medium"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/element_text"/>
</FrameLayout>

Dalsze kroki

Poniższy fragment kodu pokazuje, jak używać komponentu RecyclerView.

Kotlin


class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val dataset = arrayOf("January", "February", "March")
        val customAdapter = CustomAdapter(dataset)

        val recyclerView: RecyclerView = findViewById(R.id.recycler_view)
        recyclerView.adapter = customAdapter

    }

}

Java


RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setAdapter(customAdapter);

Biblioteka udostępnia też wiele sposobów na dostosowanie implementacji. Więcej informacji znajdziesz w artykule Zaawansowane dostosowywanie widoku RecyclerView.

Dodatkowe materiały

Więcej informacji o testowaniu na Androidzie znajdziesz w tych materiałach.

Przykładowe aplikacje