Tworzenie list dynamicznych za pomocą RecyclerView Cześć Android Jetpack.
RecyclerView ułatwia wyświetlanie dużych zbiorów danych. Wystarczy, że podasz dane i określisz 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 przewija się poza ekran, element RecyclerView nie zniszczy jego widoku. Zamiast tego RecyclerView ponownie używa widoku dla nowych elementów, które zostały przewinięte na ekranie. Funkcja RecyclerView zwiększa wydajność i czas reagowania aplikacji, a także zmniejsza zużycie energii.
Kluczowe klasy
Lista dynamiczna jest tworzona przez kilka klas.
RecyclerView
toViewGroup
, który zawiera widoki odpowiadające Twoim danym. Jest to widok, więc możesz dodaćRecyclerView
do układu w taki sam sposób jak dowolny inny element interfejsu.Każdy element na liście jest zdefiniowany przez obiekt holder widoku. Gdy tworzysz widok, nie jest z nim powiązanych żadnych danych. Po utworzeniu
RecyclerView
wiąże go z danymi. Uchwyt widoku definiuje się przez rozszerzenie widokuRecyclerView.ViewHolder
.RecyclerView
wysyła żądania widoków i wiąże je z ich danymi, wywołując metody w adapterze. Definiujesz go, rozszerzającRecyclerView.Adapter
.Menedżer układu rozmieszcza poszczególne elementy na liście. Możesz użyć jednego z menedżerów układu udostępnianych przez bibliotekę RecyclerView lub zdefiniować własnego. Menedżerowie układów są oparte na abstrakcyjnej klasie
LayoutManager
biblioteki.
Sposób działania wszystkich elementów możesz sprawdzić w próbnej aplikacji RecyclerView (Kotlin) lub próbnej aplikacji RecyclerView (Java).
Wdrażanie RecyclerView
Jeśli zamierzasz użyć obiektu RecyclerView, musisz wykonać kilka czynności. Zostały one szczegółowo wyjaśnione w kolejnych sekcjach.
Określ wygląd listy lub siatki. Zazwyczaj możesz użyć jednego ze standardowych menedżerów układu biblioteki RecyclerView.
Zaprojektuj, jak każdy element na liście wygląda i działa. Na podstawie tego projektu rozszerz klasę
ViewHolder
. Twoja wersjaViewHolder
zawiera wszystkie funkcje dotyczące elementów listy. Twój widok uchwytu to opakowanieView
, a tym widokiem zarządzaRecyclerView
.Zdefiniuj
Adapter
, który łączy Twoje dane z widokamiViewHolder
.
Dostępne są też zaawansowane opcje dostosowywania, które umożliwiają dostosowanie RecyclerView do Twoich potrzeb.
Planowanie układu
Elementy w RecyclerView są uporządkowane według klasy LayoutManager
. Biblioteka RecyclerView udostępnia 3 menedżerów układu, które obsługują większość typowych sytuacji:
LinearLayoutManager
uporządkuje elementy na jednowymiarowej liście.GridLayoutManager
umieszcza elementy w dwudwumiarowej siatce:- Jeśli siatka jest ułożona 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óżne wysokości. - Jeśli siatka jest ułożona poziomo,
GridLayoutManager
stara się, aby wszystkie elementy w każdej kolumnie miały taką samą szerokość i wysokość, ale różne kolumny mogą mieć różne szerokości.
- Jeśli siatka jest ułożona w pionie,
StaggeredGridLayoutManager
jest podobny doGridLayoutManager
, ale nie wymaga, aby elementy w wierszu miały tę samą wysokość (w przypadku siatek pionowych) lub aby elementy w tej samej kolumnie miały tę samą szerokość (w przypadku siatek poziomych). W efekcie elementy w wierszu lub kolumnie mogą być przesunięte względem siebie.
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
Po ustaleniu układu musisz zaimplementować Adapter
i ViewHolder
. Te 2 klasy współpracują ze sobą, aby określić 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 kojarzenia widoków z ich danymi nazywa się wiązaniem.
Podczas definiowania adaptera zastępujesz 3 kluczowe metody:
onCreateViewHolder()
:RecyclerView
wywołuje tę metodę, gdy musi 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()
:RecyclerView
wywołuje tę metodę, aby powiązaćViewHolder
z danymi. Metoda pobiera odpowiednie dane i wypełnia nimi układ 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()
:RecyclerView
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 elementem ViewHolder
, który wyświetla listę danych. W tym przypadku RecyclerView wyświetla prostą listę elementów tekstowych. Do adaptera przekazywana jest tablica ciągów znaków zawierająca 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 definiowany w pliku układu XML, jak zwykle.
W tym przypadku aplikacja ma plik text_row_item.xml
o takiej treści:
<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ć funkcji 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 oferuje też wiele sposobów dostosowywania implementacji. 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.