Android Kotlin Fundamentals 07.2: DiffUtil i wiązanie danych za pomocą RecyclerView

Te ćwiczenia są częścią kursu Android Kotlin Fundamentals. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. Wszystkie ćwiczenia z kursu są wymienione na stronie docelowej ćwiczeń z programowania na temat Kotlin.

Wprowadzenie

W ramach poprzedniego ćwiczenia z programem zaktualizowaliśmy funkcję TrackMySleepQuality, aby wyświetlać w RecyclerView dane o jakości snu. Metody, których się nauczyłeś, gdy tworzysz pierwsze RecyclerView, są wystarczające do większości elementów RecyclerViews, które wyświetlają proste listy, które nie są za duże. Istnieje jednak kilka technik, które sprawiają, że RecyclerView jest bardziej skuteczny w przypadku dużych list i ułatwia obsługę oraz rozbudowę złożonych list i siatki.

W tym ćwiczeniu wykorzystasz aplikację do monitorowania snu z poprzedniego ćwiczenia. Poznaj skuteczniejszy sposób aktualizowania listy danych dotyczących snu i naucz się korzystać z wiązań danych z RecyclerView. (Jeśli nie masz aplikacji z poprzedniego ćwiczenia z programowania, możesz pobrać kod startowy tego ćwiczenia).

Co musisz wiedzieć

  • Tworzenie podstawowego interfejsu użytkownika za pomocą aktywności, fragmentów i widoków danych.
  • Przechodzenie między fragmentami i przekazywanie danych między nimi za pomocą safeArgs.
  • Wyświetlanie modeli, wyświetlanie fabryk modeli, przekształceń oraz LiveData i ich obserwatorów.
  • Jak utworzyć bazę danych Room, utworzyć DAO i określić encje.
  • Jak używać algorytmów baz danych i innych długotrwałych zadań.
  • Jak wdrożyć podstawowy element RecyclerView z elementem Adapter, ViewHolder i układem elementu.

Czego się nauczysz

  • Jak używać DiffUtil, by efektywnie aktualizować listę wyświetlaną przez RecyclerView.
  • Jak używać wiązania danych z RecyclerView.
  • Jak używać adapterów wiązań do przekształcania danych.

Jakie zadania wykonasz:

  • Skorzystaj z aplikacji TrackMySleepQuality z poprzedniego ćwiczenia z tej serii.
  • Zaktualizuj SleepNightAdapter, aby skutecznie aktualizować listę za pomocą metody DiffUtil.
  • Zaimplementuj wiązanie danych w jednostce organizacyjnej RecyclerView, używając odpowiedniego adaptera, by przekształcić dane.

Aplikacja monitorowania snu ma 2 ekrany reprezentowane przez fragmenty, jak widać na rysunku poniżej.

Na pierwszym ekranie po lewej stronie znajdują się przyciski rozpoczynające i zatrzymujące śledzenie. Na ekranie pojawią się niektóre dane dotyczące snu użytkownika. Kliknięcie przycisku Wyczyść powoduje trwałe usunięcie wszystkich danych użytkownika zbieranych przez aplikację. Na drugim ekranie (po prawej) możesz wybrać ocenę jakości snu.

Ta aplikacja jest przeznaczona do użycia kontrolera interfejsu użytkownika ViewModel i LiveData oraz bazy danych Room do przechowywania danych o śnie.

Dane dotyczące snu są wyświetlane w RecyclerView. W tym ćwiczeniu z programowania tworzysz element DiffUtil i wiążące dane dla interfejsu RecyclerView. Po ukończeniu tych ćwiczeń Twoja aplikacja będzie wyglądać dokładnie tak samo, ale będzie skuteczniejsza i łatwiejsza w skalowaniu i utrzymaniu.

Możesz dalej korzystać z aplikacji SleepTracker z poprzedniego ćwiczenia z programowania. Możesz też pobrać aplikację RecyclerViewDiffUtilDataBinding-Starter z GitHuba.

  1. W razie potrzeby pobierz aplikację RecyclerViewDiffUtilDataBinding-Starter z GitHuba i otwórz projekt w Android Studio.
  2. Uruchom aplikację.
  3. Otwórz plik SleepNightAdapter.kt.
  4. Przeanalizuj kod, aby zapoznać się ze strukturą aplikacji. W tabeli poniżej znajdziesz podsumowanie informacji o tym, jak używać RecyclerView z wzorcem adaptera do wyświetlania użytkownikowi danych o śnie.

  • Na podstawie danych wejściowych użytkownika aplikacja tworzy listę obiektów SleepNight. Każdy obiekt SleepNight reprezentuje 1 noc snu, czas jego trwania oraz jakość.
  • SleepNightAdapter przekształca listę obiektów SleepNight w coś, co RecyclerView może wyświetlać i wyświetlać.
  • Adapter SleepNightAdapter tworzy kartę ViewHolders zawierającą widoki danych, dane i metadane, które zostaną wyświetlone w widoku recyklingu.
  • RecyclerView używa SleepNightAdapter do określenia liczby elementów do wyświetlenia (getItemCount()). RecyclerView używa elementów onCreateViewHolder() i onBindViewHolder(), by wskazać właścicieli widoku danych powiązanych z danymi o wyświetlaniu.

Metoda powiadomieniaDataDataChanged() jest nieskuteczna

Aby poinformować zespół RecyclerView, że element na liście został zmieniony i wymaga aktualizacji, bieżący kod wywołuje polecenie notifyDataSetChanged() w elemencie SleepNightAdapter, jak pokazano poniżej.

var data =  listOf<SleepNight>()
   set(value) {
       field = value
       notifyDataSetChanged()
   }

notifyDataSetChanged() informuje jednak zespół RecyclerView, że cała lista jest potencjalnie nieprawidłowa. W rezultacie RecyclerView ponownie łączy i ponownie usuwa każdy element na liście, w tym elementy niewidoczne na ekranie. To dużo niepotrzebna praca. W przypadku dużych i złożonych list ten proces może trwać wystarczająco długo, aby ekran migał lub przeskakiwał podczas przewijania.

Aby rozwiązać ten problem, możesz poinformować aplikację RecyclerView dokładnie, co się zmieniło. RecyclerView może wtedy zaktualizować tylko widoki danych wyświetlane na ekranie.

RecyclerView ma zaawansowany interfejs API do aktualizowania jednego elementu. Możesz użyć notifyItemChanged(), aby poinformować użytkownika RecyclerView, że element został zmieniony. Możesz też użyć podobnych funkcji w przypadku dodanych, usuniętych lub przeniesionych elementów. Można to zrobić ręcznie, ale to zadanie nie będzie proste i może wymagać dużej ilości kodu.

Na szczęście jest lepszy sposób.

DiffUtil jest wydajna i wykonuje za Ciebie ciężką pracę

RecyclerView ma klasę DiffUtil, która służy do obliczania różnic między 2 listami. DiffUtil stosuje starą i nową listę, aby pokazać, co się zmieniło. Wyszukuje elementy, które zostały dodane, usunięte lub zmienione. Następnie wykorzystuje algorytm Eugene W. (algorytm Myers&#39s).

Gdy DiffUtil wykryje, co się zmieniło, RecyclerView może wykorzystać te informacje, by zaktualizować tylko te elementy, które zostały zmienione, dodane, usunięte lub przeniesione, co jest dużo bardziej efektywne niż ponawianie całej listy.

W tym zadaniu uaktualnisz SleepNightAdapter, aby używać DiffUtil do optymalizowania RecyclerView pod kątem zmian w danych.

Krok 1. Zaimplementuj wywołanie zwrotne SleepNightDiffCallback

Aby móc korzystać z funkcji klasy DiffUtil, rozszerz właściwość DiffUtil.ItemCallback.

  1. Otwórz aplikację SleepNightAdapter.kt.
  2. Pod pełną definicją klasy SleepNightAdapter utwórz nową klasę najwyższego poziomu o nazwie SleepNightDiffCallback, która przedłuża DiffUtil.ItemCallback. Przekaż SleepNight jako parametr ogólny.
class SleepNightDiffCallback : DiffUtil.ItemCallback<SleepNight>() {
}
  1. Umieść kursor w nazwie klasy SleepNightDiffCallback.
  2. Naciśnij Alt+Enter(Option+Enter na Macu) i wybierz Wspieraj członków.
  3. W wyświetlonym oknie kliknij lewym przyciskiem myszy, aby wybrać metody areItemsTheSame() i areContentsTheSame(), a następnie kliknij OK.

    Spowoduje to wygenerowanie namiotów w SleepNightDiffCallback dla obu metod, jak pokazano poniżej. DiffUtil wykorzystuje te 2 metody, aby ustalić, jak lista i elementy się zmieniły.
    override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
  1. Zastąp areItemsTheSame() TODO kodem, który sprawdza, czy dwa przekazywane SleepNight elementy, oldItem i newItem są takie same. Jeśli elementy mają tę samą wartość nightId, są tym samym elementem, więc ustaw wartość true. W przeciwnym razie zwróć false. DiffUtil wykorzystuje ten test, aby sprawdzić, czy element został dodany, usunięty lub przeniesiony.
override fun areItemsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem.nightId == newItem.nightId
}
  1. W areContentsTheSame() sprawdź, czy wartości oldItem i newItem zawierają te same dane. W ramach tej funkcji zostaną sprawdzone wszystkie pola, ponieważ SleepNight jest klasą danych. Zajęcia w Data automatycznie określają equals i kilka innych metod. Jeśli oldItem i newItem różnią się od siebie, DiffUtil otrzyma ten kod z informacją, że element został zaktualizowany.
override fun areContentsTheSame(oldItem: SleepNight, newItem: SleepNight): Boolean {
   return oldItem == newItem
}

Typowym wzorcem jest stosowanie listy RecyclerView do wyświetlania listy, która się zmienia. Firma RecyclerView udostępnia klasę adaptera ListAdapter, która ułatwia stworzenie adaptera RecyclerView opartego na liście.

ListAdapter śledzi listę za Ciebie i powiadomi adapter o aktualizacji.

Krok 1. Zmień adapter, aby przedłużyć ListList.

  1. W pliku SleepNightAdapter.kt zmień podpis klasy SleepNightAdapter, aby wydłużyć ListAdapter.
  2. Jeśli pojawi się taka prośba, zaimportuj plik androidx.recyclerview.widget.ListAdapter.
  3. Dodaj SleepNight jako pierwszy argument do ListAdapter przed SleepNightAdapter.ViewHolder.
  4. Dodaj parametr SleepNightDiffCallback() jako parametr do konstruktora. Na podstawie tego elementu (ListAdapter) ustali, co się zmieniło na liście. Gotowy podpis zajęć SleepNightAdapter powinien wyglądać tak jak poniżej.
class SleepNightAdapter : ListAdapter<SleepNight, SleepNightAdapter.ViewHolder>(SleepNightDiffCallback()) {
  1. W ramach klasy SleepNightAdapter usuń pole data, w tym ustawienie. Nie potrzebujesz już tej listy, bo ListAdapter przechowuje ją dla Ciebie.
  2. Usuń zastąpienie wartości getItemCount(), bo metoda ListAdapter implementuje tę metodę za Ciebie.
  3. Aby usunąć błąd w elemencie onBindViewHolder(), zmień zmienną item. Zamiast używać data do item, wywołaj metodę getItem(position) dostarczoną przez ListAdapter.
val item = getItem(position)

Krok 2. Zaktualizuj listę za pomocą metody sendList()

Twój kod musi informować element ListAdapter, że dostępna jest zmieniona lista. ListAdapter udostępnia metodę submitList(), która informuje ListAdapter, że dostępna jest nowa wersja listy. Po wywołaniu tej metody ListAdapter różni nową listę od starej i znajduje elementy, które zostały dodane, usunięte, przeniesione lub zmienione. Następnie ListAdapter zaktualizuje elementy wyświetlane przez RecyclerView.

  1. Otwórz aplikację SleepTrackerFragment.kt.
  2. W onCreateView() na obserwatorze sleepTrackerViewModel znajdź błąd, w którym występuje odwołanie do usuniętej zmiennej data.
  3. Zastąp adapter.data = it połączeniem z numerem adapter.submitList(it). Zaktualizowany kod znajduje się poniżej.

sleepTrackerViewModel.nights.observe(viewLifecycleOwner, Observer {
   it?.let {
       adapter.submitList(it)
   }
})
  1. Uruchom swoją aplikację. To działa szybciej, nawet jeśli lista jest mała.

W tym zadaniu korzystasz z tej samej metody co w poprzednich ćwiczeniach z programowania, aby skonfigurować wiązanie danych, a także wyeliminujesz wywołania findViewById().

Krok 1. Dodaj wiązanie danych do pliku układu

  1. Otwórz plik układu list_item_sleep_night.xml na karcie Tekst.
  2. Umieść kursor na tagu ConstraintLayout i naciśnij Alt+Enter (Option+Enter na Macu). Otworzy się menu intencji.
  3. Wybierz Konwertuj na układ wiązania danych. Spowoduje to opakowanie układu do formatu <layout> i dodanie tagu <data>.
  4. W razie potrzeby przewiń z góry do tagu <data> i zadeklaruj zmienną o nazwie sleep.
  5. Zmień nazwę usługi type na SleepNight i com.example.android.trackmysleepquality.database.SleepNight. Gotowy tag <data> powinien wyglądać tak jak poniżej.
   <data>
        <variable
            name="sleep"
            type="com.example.android.trackmysleepquality.database.SleepNight"/>
    </data>
  1. Aby wymusić utworzenie obiektu Binding, wybierz Build > Clean Project, a następnie wybierz Build > Rebuild Project. Jeśli nadal masz problemy, wybierz Plik > Unieważnij pamięć podręczną / uruchom ponownie. Obiekt wiązania ListItemSleepNightBinding wraz z powiązanym kodem zostanie dodany do wygenerowanych plików projektu.

Krok 2. Rozszerz układ elementu za pomocą wiązania danych

  1. Otwórz aplikację SleepNightAdapter.kt.
  2. W klasie ViewHolder znajdź metodę from().
  3. Usuń deklarację zmiennej view.

Kod do usuwania:

val view = layoutInflater
       .inflate(R.layout.list_item_sleep_night, parent, false)
  1. Gdzie była zmienna view, zdefiniuj nową zmienną o nazwie binding, która zastępuje obiekt wiązania ListItemSleepNightBinding, jak pokazano poniżej. Wykonaj niezbędne importowanie obiektu wiązania.
val binding =
ListItemSleepNightBinding.inflate(layoutInflater, parent, false)
  1. Na końcu funkcji, zamiast zwracania view, zwróć binding.
return ViewHolder(binding)
  1. Aby go naprawić, umieść kursor na słowie binding. Naciśnij Alt+Enter (Option+Enter na Macu), by otworzyć menu intencji.
  1. Wybierz opcję Zmień parametr 'itemView' typ głównego konstruktora klasy 'ViewHolder' na 'ListItemSleepNightBinding'. Spowoduje to zaktualizowanie typu parametru klasy ViewHolder.

  1. Przewiń w górę do definicji klasy obiektu ViewHolder, aby zobaczyć zmianę w podpisie. Widzisz błąd w treści itemView, bo w metodzie from() została zmieniona wartość itemView na binding.

    W definicji klasy ViewHolder kliknij prawym przyciskiem myszy jedno z wystąpień itemView i wybierz Refaktor i Zmień nazwę. Zmień nazwę na binding.
  2. Prefiks parametru konstruktora binding dodaj do elementu val, aby ustawić go jako właściwość.
  3. W wywołaniu klasy nadrzędnej RecyclerView.ViewHolder zmień parametr z binding na binding.root. Musisz przekazać View, a binding.root jest głównym elementem ConstraintLayout w układzie elementu.
  4. Ukończona deklaracja zajęć powinna wyglądać jak kod poniżej.
class ViewHolder private constructor(val binding: ListItemSleepNightBinding) : RecyclerView.ViewHolder(binding.root){

Zobaczysz też błąd w połączeniach z findViewById() i naprawisz to.

Krok 3. Zastąp funkcję FindViewById()

Możesz teraz zaktualizować właściwości sleepLength, quality i qualityImage, aby korzystały z obiektu binding zamiast findViewById().

  1. Aby zmienić widok danych obiektu binding, zmień inicjacje obiektów sleepLength, qualityString i qualityImage, jak pokazano poniżej. Od tego momentu kod nie powinien już podawać błędów.
val sleepLength: TextView = binding.sleepLength
val quality: TextView = binding.qualityString
val qualityImage: ImageView = binding.qualityImage

Po utworzeniu obiektu wiązania nie musisz już definiować właściwości sleepLength, quality ani qualityImage. DataBinding przechowuje w pamięci podręcznej wyszukiwania, więc nie trzeba deklarować tych właściwości.

  1. Kliknij prawym przyciskiem myszy nazwy właściwości sleepLength, quality i qualityImage. Wybierz Fact > Inline lub naciśnij Control+Command+N (Option+Command+N na Macu).
  2. Uruchom aplikację. Jeśli zauważysz błędy, być może trzeba będzie wyczyścić i utworzyć ponownie projekt.

W tym zadaniu uaktualnisz aplikację, by korzystała z wiązania danych z adapterami wiązań, aby ustawiać dane w widokach.

W poprzednim ćwiczeniu z programowania użyto klasy Transformations, aby utworzyć LiveData i wygenerować sformatowane ciągi znaków do wyświetlenia w widokach tekstowych. Jeśli jednak chcesz utworzyć powiązanie różnych typów lub złożonych typów, możesz udostępnić adaptery wiązania, by ułatwić wiązanie danych. Adaptery to adaptery, które pobierają dane i przekształcają je w element, za pomocą którego ta funkcja może powiązać widok, np. tekst lub obraz.

Wdróżesz trzy adaptery: po jednym dla obrazu wysokiej jakości i jeden dla każdego pola tekstowego. W skrócie: aby zadeklarować adapter wiązania, musisz zdefiniować metodę, która wykorzystuje element i widok, i dodać do nich adnotacje za pomocą @BindingAdapter. W treści metody przeprowadzasz przekształcenie. W Kotlin można napisać adapter wiązania jako funkcję rozszerzenia w klasie widoku danych, która odbiera dane.

Krok 1. Utwórz adaptery wiązań

Pamiętaj, że w tym kroku musisz zaimportować wiele zajęć. Nie będą one wywoływane pojedynczo.

  1. Otwórz aplikację SleepNightAdapater.kt.
  2. W klasie ViewHolder znajdź metodę bind() i przypomnij sobie, jak działa. Pobierz kod, który oblicza wartości binding.sleepLength, binding.quality i binding.qualityImage, i użyj go w adapterze. Na razie pozostaw kod bez zmian – przenieś go w późniejszym kroku.
  3. W pakiecie sleeptracker utwórz i otwórz plik o nazwie BindingUtils.kt.
  4. Zadeklaruj funkcję rozszerzenia w TextView o nazwie setSleepDurationFormatted i przekaż SleepNight. Ta funkcja będzie adapterem do obliczania i formatowania czasu trwania snu.
fun TextView.setSleepDurationFormatted(item: SleepNight) {}
  1. W treści setSleepDurationFormatted utwórz powiązanie danych z widokiem danych, tak jak w narzędziu ViewHolder.bind(). Wywołaj convertDurationToFormatted(), a następnie ustaw text w TextView na sformatowany tekst. (To jest funkcja rozszerzenia w TextView, więc masz bezpośredni dostęp do właściwości text).
text = convertDurationToFormatted(item.startTimeMilli, item.endTimeMilli, context.resources)
  1. Aby poinformować wiązanie danych o tym adapterze, dodaj do funkcji adnotacje funkcji @BindingAdapter.
  2. Ta funkcja jest adapterem atrybutu sleepDurationFormatted, więc przekaż sleepDurationFormatted jako argument do @BindingAdapter.
@BindingAdapter("sleepDurationFormatted")
  1. Drugi adapter ustawia jakość snu na podstawie wartości obiektu SleepNight. Utwórz funkcję rozszerzenia o nazwie setSleepQualityString() w dniu TextView i przekaż SleepNight.
  2. W treści artykułu utwórz powiązanie danych z widokiem danych, tak jak w przypadku elementu ViewHolder.bind(). Zadzwoń do: convertNumericQualityToString i ustaw text.
  3. Dodaj adnotację do funkcji @BindingAdapter("sleepQualityString").
@BindingAdapter("sleepQualityString")
fun TextView.setSleepQualityString(item: SleepNight) {
   text = convertNumericQualityToString(item.sleepQuality, context.resources)
}
  1. Trzeci adapter wiązania ustawia obraz w widoku obrazu. Utwórz funkcję rozszerzenia w ImageView i zadzwoń do setSleepImage, a następnie użyj kodu z ViewHolder.bind(), jak pokazano poniżej.
@BindingAdapter("sleepImage")
fun ImageView.setSleepImage(item: SleepNight) {
   setImageResource(when (item.sleepQuality) {
       0 -> R.drawable.ic_sleep_0
       1 -> R.drawable.ic_sleep_1
       2 -> R.drawable.ic_sleep_2
       3 -> R.drawable.ic_sleep_3
       4 -> R.drawable.ic_sleep_4
       5 -> R.drawable.ic_sleep_5
       else -> R.drawable.ic_sleep_active
   })
}

Krok 2. Zaktualizuj SleepNightAdapter

  1. Otwórz aplikację SleepNightAdapter.kt.
  2. Usuń wszystko z metody bind(), ponieważ możesz teraz użyć wiązania danych i nowych adapterów, aby to zrobić.
fun bind(item: SleepNight) {
}
  1. W ramach bind() przypisz sen do: item, ponieważ musisz wskazać obiekt wiążący dotyczący nowego elementu SleepNight.
binding.sleep = item
  1. Poniżej tego wiersza dodaj binding.executePendingBindings(). To wywołanie to optymalizacja, która wymaga, aby wiązanie danych zostało natychmiast wykonane. Zawsze warto wywoływać interfejs executePendingBindings(), gdy używasz adapterów wiązania w RecyclerView, bo może to nieco zwiększyć rozmiar widoków.
 binding.executePendingBindings()

Krok 3. Dodaj wiązania do układu XML

  1. Otwórz aplikację list_item_sleep_night.xml.
  2. W polu ImageView dodaj właściwość app o tej samej nazwie co adapter wiążący, który ustawia obraz. Przekaż zmienną sleep zgodnie z poniższym opisem.

    Ta właściwość tworzy połączenie między widokiem danych a obiektem wiązania za pomocą adaptera. Jeśli nastąpi wywołanie funkcji sleepImage, adapter dostosuje dane z SleepNight.
app:sleepImage="@{sleep}"
  1. Zrób to samo w widokach tekstu sleep_length i quality_string. Za każdym razem, gdy użyto odniesienia sleepDurationFormatted lub sleepQualityString, adaptery dostosowują dane z SleepNight.
app:sleepDurationFormatted="@{sleep}"
app:sleepQualityString="@{sleep}"
  1. Uruchom aplikację. Działa ona dokładnie tak samo jak wcześniej. Adaptery wiążą się z całą pracą nad formatowaniem i aktualizowaniem widoków po zmianie danych, upraszczając ViewHolder i ulepszając kod znacznie lepiej niż dotychczas.

W przypadku kilku ostatnich ćwiczeń ta sama lista została wyświetlona. Została ona zaprojektowana tak, aby pokazać Ci, że interfejs Adapter umożliwia projektowanie Twojego kodu na wiele różnych sposobów. Im bardziej złożony kod, tym większe znaczenie ma jego architektura. W aplikacjach produkcyjnych te wzorce i inne są używane w RecyclerView. Wzorce działają prawidłowo, a każdy z nich ma swoje zalety. Wybór zależy od tego, co tworzysz.

Gratulacje! Jesteś na dobrej drodze, by opanować grę RecyclerView na Androidzie.

Projekt na Android Studio: RecyclerViewDiffUtilDataBinding.

DiffUtil:

  • RecyclerView ma klasę DiffUtil, która służy do obliczania różnic między 2 listami.
  • Klasa DiffUtil ma klasę ItemCallBack, którą wydłużasz, aby określić różnicę między 2 listami.
  • W klasie ItemCallback musisz zastąpić metody areItemsTheSame() i areContentsTheSame().

ListAdapter:

  • Aby bezpłatnie zarządzać listą, możesz użyć klasy ListAdapter zamiast RecyclerView.Adapter. Jeśli jednak używasz ListAdapter, musisz przygotować własny adapter dla innych układów, dlatego to ćwiczenie ćwiczeń pokazuje, jak to zrobić.
  • Aby otworzyć menu intencji w Android Studio, umieść kursor na dowolnym elemencie kodu i naciśnij Alt+Enter (Option+Enter na Macu). To menu jest szczególnie przydatne w przypadku refaktoryzacji kodu i tworzenia wycinków do implementacji metod. Sposób obsługi menu zależy od kontekstu – musisz go dokładnie umieścić na kursoru.

Powiązanie danych:

  • Wiązanie danych w układzie elementu umożliwia powiązanie danych z widokami.

Adaptery wiążące:

  • Wcześniej do tworzenia ciągów danych na podstawie tych danych użyto Transformations. Jeśli chcesz powiązać dane różnych lub złożonych typów, użyj adapterów wiązań, by ułatwić ich używanie.
  • Aby zadeklarować adapter wiązania, zdefiniuj metodę, która akceptuje element i widok, i dodaj adnotację do metody metodą @BindingAdapter. W Kotlin można zapisać adapter wiązania jako funkcję rozszerzenia w View. Przekaż nazwę właściwości adaptowanej przez adapter. Przykład:
@BindingAdapter("sleepDurationFormatted")
  • W układzie XML ustaw właściwość app o tej samej nazwie co adapter wiążący. Przekaż zmienną na podstawie danych. Przykład:
.app:sleepDurationFormatted="@{sleep}"

Kursy Udacity:

Dokumentacja dla programistów Androida:

Inne zasoby:

Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:

  • W razie potrzeby przypisz zadanie domowe.
  • Poinformuj uczniów, jak przesyłać zadania domowe.
  • Oceń projekty domowe.

Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.

Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.

Odpowiedz na te pytania

Pytanie 1

Które z poniższych działań są konieczne do korzystania z DiffUtil? Wybierz wszystkie pasujące odpowiedzi.

▢ Rozszerzenie klasy ItemCallBack.

▢ Zastąp areItemsTheSame().

▢ Zastąp areContentsTheSame().

▢ Do śledzenia różnic między elementami używaj wiązania danych.

Pytanie 2

Które z poniższych stwierdzeń na temat adapterów wiązań jest prawdziwe?

▢ Adapter wiążący to funkcja opatrzona adnotacją @BindingAdapter.

▢ Użyj adaptera wiązania, aby oddzielić formatowanie danych od widoku.

▢ Jeśli chcesz używać adapterów wiązań, musisz użyć znacznika RecyclerViewAdapter.

▢ Adaptery wiązania są dobrym rozwiązaniem, gdy chcesz przekształcić złożone dane.

Pytanie 3

Kiedy lepiej użyć Transformations zamiast adaptera wiążącego? Wybierz wszystkie pasujące odpowiedzi.

▢ Twoje dane są proste;

▢ Formatowanie ciągu znaków.

▢ Twoja lista jest bardzo długa.

ViewHolder zawiera tylko jeden widok.

Rozpocznij następną lekcję: 7.3: GridLayout z RecyclerView