Tworzenie list dynamicznych za pomocą RecyclerView Część Android Jetpack.
RecyclerView ułatwia wyświetlanie dużych zbiorów danych. Ty dostarczasz dane i określasz wygląd każdego elementu, a biblioteka RecyclerView dynamicznie tworzy elementy, gdy są potrzebne.
Jak sama nazwa wskazuje, RecyclerView przetwarza te poszczególne elementy. Gdy element zniknie z ekranu, RecyclerView nie zniszczy jego widoku. Zamiast tego RecyclerView ponownie używa widoku dla nowych elementów, które zostały przewinięte na ekranie. RecyclerView zwiększa wydajność i szybkość reakcji aplikacji oraz 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, w jaki dodajesz inne elementy 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. Widok uchwytu definiujesz, rozszerzając elementRecyclerView.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 chcesz użyć RecyclerView, musisz wykonać kilka czynności. Zostały one szczegółowo opisane w następnych sekcjach.
Określ wygląd listy lub siatki. Zazwyczaj możesz użyć jednego ze standardowych menedżerów układu biblioteki RecyclerView.
Zaprojektuj wygląd i działanie każdego elementu na liście. 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 związanych z układem:
LinearLayoutManager
umieszcza elementy na liście jednowymiarowej.GridLayoutManager
umieszcza elementy w dwudwumiarowej siatce:- Jeśli siatka jest ułożona w poziomie,
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 poziomie,
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 widoku zasobnika, 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 element opakowujący View
, który zawiera układ pojedynczego elementu na liście. W razie potrzeby usługa Adapter
tworzy obiekty ViewHolder
, a także 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
. Metoda tworzy i inicjalizuje tabelęViewHolder
oraz powiązaną z nią tabelęView
, ale nie wypełnia zawartości widoku – tabelaViewHolder
nie została jeszcze powiązana 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źć odpowiednią nazwę na liście i wypełnić widgetTextView
widoczny dla właściciela.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. RecyclerView używa tego, aby określić, kiedy nie ma już żadnych elementów do wyświetlenia.
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
Ten 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 Zaawansowana personalizacja RecyclerView.
Dodatkowe materiały
Więcej informacji o testowaniu na Androidzie znajdziesz w tych materiałach.