Twórz dynamiczne listy za pomocą RecyclerView. Zawiera Android Jetpack.
RecyclerView ułatwia efektywne wyświetlanie dużych zbiorów danych. Wystarczy podać dane i określić wygląd każdego elementu, a biblioteka RecyclerView dynamicznie tworzy te elementy, gdy są potrzebne.
Jak wskazuje nazwa, element RecyclerView recyklinguje te pojedyncze elementy. Gdy element przewinie się poza ekran, element RecyclerView nie zniszczy jego widoku. Zamiast tego obiekt RecyclerView będzie ponownie wykorzystywać widok do tworzenia nowych elementów, które zostały przewinięte na ekran. Funkcja RecyclerView zwiększa wydajność i czas reagowania aplikacji, a także zmniejsza zużycie energii.
Kluczowe klasy
Kilka zajęć musi ze sobą współpracować, by utworzyć dynamiczną listę.
RecyclerView
toViewGroup
, który zawiera widoki odpowiadające Twoim danym. To sam widok, więc dodajeszRecyclerView
do układu w taki sam sposób, w jaki dodajesz inne elementy interfejsu.Każdy element na liście jest definiowany przez obiekt obiektu widoku. Po utworzeniu właściciela widoku nie są z nim powiązane żadne dane. Po utworzeniu właściciela widoku obiekt
RecyclerView
wiąże go ze swoimi danymi. Uchwyt widoku definiuje się przez rozszerzenie widokuRecyclerView.ViewHolder
.RecyclerView
żąda widoków i wiąże je z ich danymi, wywołując metody w adapterze. Definiujesz adapter, przedłużając ciągRecyclerView.Adapter
.Menedżer układu porządkuje poszczególne elementy na liście. Możesz użyć jednego z menedżerów układu dostępnych w bibliotece RecyclerView lub zdefiniować własne. Menedżerowie układu są oparte na klasie abstrakcyjnej
LayoutManager
biblioteki.
Aby zobaczyć, jak wszystkie elementy się ze sobą łączą, skorzystaj z przykładowej aplikacji RecyclerView (Kotlin) lub przykładowej aplikacji RecyclerView (Java).
Etapy wdrażania elementu RecyclerView
Jeśli zamierzasz użyć obiektu RecyclerView, musisz wykonać kilka czynności. Zostały one szczegółowo wyjaśnione w kolejnych sekcjach.
Wybierz wygląd listy lub siatki. Zwykle można użyć jednego z menedżerów układu dostępnych w bibliotece RecyclerView.
Zaprojektuj, jak każdy element na liście wygląda i działa. Biorąc pod uwagę ten projekt, rozszerz klasę
ViewHolder
. Twoja wersjaViewHolder
udostępnia wszystkie funkcje elementów listy. Obiekt widoku danych łączy się z elementemView
, a tym widokiem zarządzaRecyclerView
.Określ
Adapter
, który wiąże Twoje dane z widokamiViewHolder
.
Dostępne są też zaawansowane opcje dostosowywania, które umożliwiają dostosowanie widoku RecyclerView do własnych potrzeb.
Planowanie układu
Elementy w obiekcie 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
uporządkuje elementy na jednowymiarowej liście.GridLayoutManager
układa elementy w dwuwymiarową siatkę:- Jeśli siatka jest ustawiona w pionie,
GridLayoutManager
stara się, aby wszystkie elementy w każdym wierszu miały taką samą szerokość i wysokość, ale różne wiersze mogą mieć różną wysokość. - Jeśli siatka jest ustawiona w poziomie,
GridLayoutManager
stara się, aby wszystkie elementy w każdej kolumnie miały taką samą szerokość i wysokość, ale różne kolumny mogą mieć różną szerokość.
- Jeśli siatka jest ustawiona w pionie,
StaggeredGridLayoutManager
działa podobnie doGridLayoutManager
, ale nie wymaga, aby elementy w wierszu miały taką samą wysokość (w przypadku siatek pionowych) ani elementy w tej samej kolumnie (w przypadku siatek poziomych). W efekcie elementy w wierszu lub kolumnie mogą być od siebie przesunięte.
Musisz też zaprojektować układ poszczególnych elementów. Ten układ jest potrzebny podczas projektowania uchwytu widoku, jak opisano w następnej sekcji.
Wdrażanie adaptera i uchwytu widoku
Po określeniu układu musisz wdrożyć Adapter
i ViewHolder
. Te 2 klasy wspólnie określają sposób wyświetlania danych. ViewHolder
to otoka wokół elementu View
, która zawiera układ konkretnego elementu na liście. W razie potrzeby Adapter
tworzy obiekty ViewHolder
i ustawia dane dla tych widoków. Proces wiązania widoków danych z ich danymi nazywa się wiązywaniem.
Gdy definiujesz adapter, zastępujesz trzy kluczowe metody:
onCreateViewHolder()
:RecyclerView
wywołuje tę metodę za każdym razem, gdy trzeba utworzyć nowy obiektViewHolder
. Ta metoda tworzy i inicjuje obiektViewHolder
oraz powiązany z nim elementView
, ale nie wypełnia zawartości widoku – obiektViewHolder
nie jest jeszcze powiązany z konkretnymi danymi.onBindViewHolder()
: funkcjaRecyclerView
wywołuje tę metodę, aby powiązać elementViewHolder
z danymi. Metoda pobiera odpowiednie dane i wykorzystuje je do wypełniania układu właściciela widoku. Jeśli na przykładRecyclerView
wyświetla listę nazw, metoda może znaleźć na liście odpowiednią nazwę i wypełnić widżetTextView
właściciela widoku.getItemCount()
: funkcjaRecyclerView
wywołuje tę metodę, aby uzyskać rozmiar zbioru danych. Na przykład w aplikacji książki adresowej może to być łączna liczba adresów. Funkcja RecyclerView korzysta z niej, 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 obiektem ViewHolder
, który wyświetla listę danych. W tym przypadku RecyclerView wyświetla prostą listę elementów tekstowych. Adapter jest przekazywany do 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 jak zwykle zdefiniowany w pliku układu XML.
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 korzystać z narzędzia 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.layoutManager = LinearLayoutManager(this) recyclerView.adapter = customAdapter } }
Java
RecyclerView recyclerView = findViewById(R.id.recycler_view); recyclerView.layoutManager = new LinearLayoutManager(this) recyclerView.setAdapter(customAdapter);
Biblioteka umożliwia też dostosowanie implementacji na wiele sposobów. Więcej informacji znajdziesz w artykule na temat zaawansowanych dostosowań elementu RecyclerView.
Dodatkowe materiały
Więcej informacji o testowaniu na Androidzie znajdziesz w tych materiałach.