Twórz dynamiczne listy za pomocą RecyclerView w ramach Androida Jetpack.
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
toViewGroup
, który zawiera widoki danych odpowiadające Twoim danym. To widok, więc dodajesz do układu elementRecyclerView
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 komponentRecyclerView.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 wymiarRecyclerView.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.
Wybierz wygląd listy lub siatki. Zwykle można użyć jednego ze standardowych menedżerów układu biblioteki RecyclerView.
Zaprojektuj wygląd i zachowanie każdego elementu na liście. Na podstawie tego projektu rozszerz klasę
ViewHolder
. Twoja wersjaViewHolder
oferuje wszystkie funkcje związane z elementami list. Widok ten otacza elementView
, a widokiem tym zarządzaRecyclerView
.Określ
Adapter
, który wiąże Twoje dane z widokamiViewHolder
.
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ść.
- Jeśli siatka jest ustawiona pionowo,
- Kolumna
StaggeredGridLayoutManager
jest podobna do właściwościGridLayoutManager
, 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 elementuViewHolder
. Ta metoda tworzy i inicjuje obiektViewHolder
oraz powiązaną z nimView
, ale nie wypełnia treści widoku – elementViewHolder
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ładRecyclerView
wyświetla listę nazw, metoda może znaleźć odpowiednią nazwę na liście i wypełnić widżetTextView
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.