Ten moduł Codelab jest częścią kursu Android Kotlin Fundamentals. Najwięcej korzyści przyniesie Ci ukończenie wszystkich ćwiczeń w kolejności. Wszystkie ćwiczenia z tego kursu znajdziesz na stronie docelowej kursu Android Kotlin Fundamentals.
Wprowadzenie
W tym ćwiczeniu w Codelabs przypomnimy sobie, jak używać ViewModel i fragmentów do implementowania nawigacji. Pamiętaj, że celem jest umieszczenie logiki when w ViewModel, ale ścieżki należy zdefiniować we fragmentach i w pliku nawigacyjnym. Aby to osiągnąć, używasz modeli widoku, fragmentów, LiveData i obserwatorów.
Na koniec tego samouczka pokazujemy sprytny sposób śledzenia stanów przycisków przy użyciu minimalnej ilości kodu, dzięki czemu każdy przycisk jest włączony i można go kliknąć tylko wtedy, gdy ma to sens dla użytkownika.
Co warto wiedzieć
Musisz znać:
- Tworzenie podstawowego interfejsu użytkownika za pomocą aktywności, fragmentów i widoków.
- Przechodzenie między fragmentami i używanie
safeArgsdo przekazywania danych między nimi. - Wyświetlanie modeli, fabryk modeli, przekształceń i
LiveDataoraz ich obserwatorów. - Jak utworzyć bazę danych
Room, obiekt dostępu do danych (DAO) i zdefiniować encje. - Jak używać korutyn do interakcji z bazą danych i innych długotrwałych zadań.
Czego się nauczysz
- Jak zaktualizować w bazie danych istniejący zapis jakości snu.
- Jak używać
LiveDatado śledzenia stanów przycisków. - Jak wyświetlić pasek z informacją w odpowiedzi na zdarzenie.
Jakie zadania wykonasz
- Rozszerz aplikację TrackMySleepQuality, aby zbierać ocenę jakości, dodawać ją do bazy danych i wyświetlać wynik.
- Użyj
LiveData, aby wyświetlić pasek powiadomień. - Aby włączyć i wyłączyć przyciski, użyj
LiveData.
W tym ćwiczeniu utworzysz funkcję rejestrowania jakości snu i ukończysz interfejs aplikacji TrackMySleepQuality.
Aplikacja ma 2 ekrany reprezentowane przez fragmenty, jak pokazano na ilustracji poniżej.
Na pierwszym ekranie (po lewej) znajdują się przyciski rozpoczynania i zatrzymywania śledzenia. Na ekranie wyświetlają się wszystkie dane snu użytkownika. Przycisk Wyczyść trwale usuwa wszystkie dane zebrane przez aplikację na temat użytkownika.
Drugi ekran, widoczny po prawej stronie, służy do wybierania oceny jakości snu. W aplikacji ocena jest przedstawiana w formie liczbowej. Na potrzeby programowania aplikacja wyświetla zarówno ikony twarzy, jak i ich odpowiedniki liczbowe.
Proces wygląda następująco:
- Użytkownik otwiera aplikację i widzi ekran śledzenia snu.
- Użytkownik klika przycisk Rozpocznij. Zapisuje to czas rozpoczęcia i wyświetla go. Przycisk Start jest wyłączony, a przycisk Stop jest włączony.
- Użytkownik klika przycisk Zatrzymaj. Zapisze to czas zakończenia i otworzy ekran jakości snu.
- Użytkownik wybiera ikonę jakości snu. Ekran zamyka się, a na ekranie śledzenia wyświetla się godzina zakończenia snu i jego jakość. Przycisk Stop jest wyłączony, a przycisk Start jest włączony. Aplikacja jest gotowa na kolejną noc.
- Przycisk Wyczyść jest włączony, gdy w bazie danych znajdują się dane. Gdy użytkownik kliknie przycisk Wyczyść, wszystkie jego dane zostaną bezpowrotnie usunięte – nie pojawi się komunikat „Czy na pewno?”.
Ta aplikacja korzysta z uproszczonej architektury, jak pokazano poniżej w kontekście pełnej architektury. Aplikacja korzysta tylko z tych komponentów:
- kontroler interfejsu,
- Wyświetl model i
LiveData - baza danych Room,
W tym ćwiczeniu w Codelabs zakładamy, że wiesz, jak implementować nawigację za pomocą fragmentów i pliku nawigacji. Aby ułatwić Ci pracę, udostępniamy sporą część tego kodu.
Krok 1. Sprawdź kod
- Aby rozpocząć, użyj własnego kodu z końca ostatniego ćwiczenia lub pobierz kod startowy.
- W kodzie początkowym sprawdź
SleepQualityFragment. Ta klasa rozszerza układ, pobiera aplikację i zwracabinding.root. - Otwórz plik navigation.xml w edytorze projektu. Widzisz, że istnieje ścieżka nawigacji z
SleepTrackerFragmentdoSleepQualityFragmenti zSleepQualityFragmentdoSleepTrackerFragment.
- Sprawdź kod pod kątem navigation.xml. W szczególności poszukaj
<argument>o nazwiesleepNightKey.
Gdy użytkownik przechodzi zSleepTrackerFragmentdoSleepQualityFragment,, aplikacja przekazujesleepNightKeydoSleepQualityFragmentw przypadku nocy, która wymaga aktualizacji.
Krok 2. Dodaj nawigację do śledzenia jakości snu
W grafie nawigacji są już ścieżki z SleepTrackerFragment do SleepQualityFragment i z powrotem. Nie ma jednak jeszcze kodu obsługi kliknięć, który implementuje nawigację z jednego fragmentu do drugiego. Dodaj ten kod w ViewModel.
W funkcji obsługi kliknięć ustawiasz LiveData, który zmienia się, gdy chcesz, aby aplikacja przechodziła do innego miejsca docelowego. Fragment przestrzega tego LiveData. Gdy dane się zmienią, fragment przejdzie do miejsca docelowego i powiadomi model widoku, że zadanie zostało wykonane, co spowoduje zresetowanie zmiennej stanu.
- Otwórz pokój
SleepTrackerViewModel. Musisz dodać nawigację, aby po kliknięciu przez użytkownika przycisku Stop aplikacja przechodziła do ekranuSleepQualityFragment, na którym można ocenić jakość. - W
SleepTrackerViewModelutwórzLiveData, który będzie się zmieniać, gdy chcesz, aby aplikacja przechodziła doSleepQualityFragment. Użyj hermetyzacji, aby udostępnić tylko wersjęLiveData, którą można pobrać, wViewModel.
Ten kod możesz umieścić w dowolnym miejscu na najwyższym poziomie treści zajęć.
private val _navigateToSleepQuality = MutableLiveData<SleepNight>()
val navigateToSleepQuality: LiveData<SleepNight>
get() = _navigateToSleepQuality- Dodaj funkcję
doneNavigating(), która resetuje zmienną wywołującą nawigację.
fun doneNavigating() {
_navigateToSleepQuality.value = null
}- W funkcji obsługi kliknięcia przycisku Stop
onStopTracking()wywołaj przejście doSleepQualityFragment. Ustaw zmienną _navigateToSleepQualityna końcu funkcji jako ostatni element w blokulaunch{}. Pamiętaj, że ta zmienna jest ustawiona nanight. Gdy ta zmienna ma wartość, aplikacja przechodzi doSleepQualityFragment, przekazując noc.
_navigateToSleepQuality.value = oldNightSleepTrackerFragmentmusi obserwować _navigateToSleepQuality, aby aplikacja wiedziała, kiedy przejść do następnego ekranu. WSleepTrackerFragmentwonCreateView()dodaj obserwatora dlanavigateToSleepQuality(). Pamiętaj, że import w tym przypadku jest niejednoznaczny i musisz zaimportowaćandroidx.lifecycle.Observer.
sleepTrackerViewModel.navigateToSleepQuality.observe(this, Observer {
})
- W bloku obserwatora przejdź do identyfikatora bieżącej nocy i przekaż go dalej, a następnie wywołaj funkcję
doneNavigating(). Jeśli import jest niejednoznaczny, zaimportujandroidx.navigation.fragment.findNavController.
night ->
night?.let {
this.findNavController().navigate(
SleepTrackerFragmentDirections
.actionSleepTrackerFragmentToSleepQualityFragment(night.nightId))
sleepTrackerViewModel.doneNavigating()
}- Zbuduj i uruchom aplikację. Kliknij Start, a potem Stop. Spowoduje to przejście do ekranu
SleepQualityFragment. Aby wrócić, użyj systemowego przycisku Wstecz.
W tym zadaniu zapiszesz jakość snu i wrócisz do fragmentu śledzenia snu. Wyświetlacz powinien automatycznie zaktualizować się, aby pokazać użytkownikowi zaktualizowaną wartość. Musisz utworzyć ViewModel i ViewModelFactory oraz zaktualizować SleepQualityFragment.
Krok 1. Utwórz ViewModel i ViewModelFactory
- W pakiecie
sleepqualityutwórz lub otwórz plik SleepQualityViewModel.kt. - Utwórz klasę
SleepQualityViewModel, która przyjmuje jako argumentysleepNightKeyi bazę danych. Podobnie jak w przypadkuSleepTrackerViewModel, musisz przekazaćdatabasez fabryki. Musisz też przekazaćsleepNightKeyz nawigacji.
class SleepQualityViewModel(
private val sleepNightKey: Long = 0L,
val database: SleepDatabaseDao) : ViewModel() {
}- W klasie
SleepQualityViewModelzdefiniujJobiuiScopeoraz zastąponCleared().
private val viewModelJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
override fun onCleared() {
super.onCleared()
viewModelJob.cancel()
}- Aby wrócić do
SleepTrackerFragment, używając tego samego wzorca co powyżej, zadeklaruj_navigateToSleepTracker. Zaimplementuj funkcjenavigateToSleepTrackeridoneNavigating().
private val _navigateToSleepTracker = MutableLiveData<Boolean?>()
val navigateToSleepTracker: LiveData<Boolean?>
get() = _navigateToSleepTracker
fun doneNavigating() {
_navigateToSleepTracker.value = null
}- Utwórz jeden moduł obsługi kliknięć,
onSetSleepQuality(), do użycia we wszystkich obrazach dotyczących jakości snu.
Użyj tego samego wzorca korutyny co w poprzednim laboratorium:
- Uruchom korutynę w
uiScopei przełącz się na dyspozytor wejścia/wyjścia. - Otrzymaj
tonight, korzystając zsleepNightKey. - Ustaw jakość snu.
- Zaktualizuj bazę danych.
- Wywołaj nawigację.
Zwróć uwagę, że w przykładzie kodu poniżej cała praca jest wykonywana w procedurze obsługi kliknięcia, zamiast wyodrębniać operację na bazie danych w innym kontekście.
fun onSetSleepQuality(quality: Int) {
uiScope.launch {
// IO is a thread pool for running operations that access the disk, such as
// our Room database.
withContext(Dispatchers.IO) {
val tonight = database.get(sleepNightKey) ?: return@withContext
tonight.sleepQuality = quality
database.update(tonight)
}
// Setting this state variable to true will alert the observer and trigger navigation.
_navigateToSleepTracker.value = true
}
}- W pakiecie
sleepqualityutwórz lub otwórz plikSleepQualityViewModelFactory.kti dodaj klasęSleepQualityViewModelFactory, jak pokazano poniżej. Ta klasa używa wersji tego samego kodu szablonowego, który już znasz. Sprawdź kod, zanim przejdziesz dalej.
class SleepQualityViewModelFactory(
private val sleepNightKey: Long,
private val dataSource: SleepDatabaseDao) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(SleepQualityViewModel::class.java)) {
return SleepQualityViewModel(sleepNightKey, dataSource) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}Krok 2. Zaktualizuj element SleepQualityFragment
- Otwórz pokój
SleepQualityFragment.kt. - W
onCreateView()po otrzymaniuapplicationmusisz pobraćarguments, który był dołączony do nawigacji. Te argumenty są wSleepQualityFragmentArgs. Musisz je wyodrębnić z pakietu.
val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)- Następnie zdobądź
dataSource.
val dataSource = SleepDatabase.getInstance(application).sleepDatabaseDao- Utwórz fabrykę, przekazując
dataSourceisleepNightKey.
val viewModelFactory = SleepQualityViewModelFactory(arguments.sleepNightKey, dataSource)- Uzyskaj referencję
ViewModel.
val sleepQualityViewModel =
ViewModelProviders.of(
this, viewModelFactory).get(SleepQualityViewModel::class.java)- Dodaj
ViewModeldo obiektu powiązania. (Jeśli zobaczysz błąd dotyczący obiektu powiązania, na razie go zignoruj).
binding.sleepQualityViewModel = sleepQualityViewModel- Dodaj obserwatora. Gdy pojawi się prośba, zaimportuj
androidx.lifecycle.Observer.
sleepQualityViewModel.navigateToSleepTracker.observe(this, Observer {
if (it == true) { // Observed state is true.
this.findNavController().navigate(
SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
sleepQualityViewModel.doneNavigating()
}
})Krok 3. Zaktualizuj plik układu i uruchom aplikację
- Otwórz plik układu
fragment_sleep_quality.xml. W bloku<data>dodaj zmienną dlaSleepQualityViewModel.
<data>
<variable
name="sleepQualityViewModel"
type="com.example.android.trackmysleepquality.sleepquality.SleepQualityViewModel" />
</data>- Do każdego z 6 obrazów dotyczących jakości snu dodaj obsługę kliknięcia, taką jak poniżej. Dopasuj ocenę jakości do obrazu.
android:onClick="@{() -> sleepQualityViewModel.onSetSleepQuality(5)}"- Wyczyść i ponownie skompiluj projekt. Powinno to rozwiązać wszelkie błędy związane z obiektem wiązania. W przeciwnym razie wyczyść pamięć podręczną (File > Invalidate Caches / Restart) i ponownie skompiluj aplikację.
Gratulacje! Właśnie udało Ci się utworzyć kompletną aplikację bazy danych Room za pomocą korutyn.
Teraz aplikacja działa prawidłowo. Użytkownik może klikać Start i Stop dowolną liczbę razy. Gdy użytkownik kliknie Stop (Zakończ), może ocenić jakość snu. Gdy użytkownik kliknie Wyczyść, wszystkie dane zostaną wyczyszczone w tle bez powiadomienia. Wszystkie przyciski są jednak zawsze włączone i można je kliknąć, co nie powoduje awarii aplikacji, ale umożliwia użytkownikom tworzenie niepełnych nocy snu.
W tym ostatnim zadaniu dowiesz się, jak używać map przekształceń do zarządzania widocznością przycisków, aby użytkownicy mogli dokonywać tylko właściwych wyborów. Możesz użyć podobnej metody, aby wyświetlić przyjazny komunikat po wyczyszczeniu wszystkich danych.
Krok 1. Zaktualizuj stany przycisków
Chodzi o ustawienie stanu przycisku tak, aby na początku tylko przycisk Start był włączony, czyli klikalny.
Gdy użytkownik kliknie Start, przycisk Stop zostanie włączony, a przycisk Start – wyłączony. Przycisk Wyczyść jest włączony tylko wtedy, gdy w bazie danych znajdują się dane.
- Otwórz plik układu
fragment_sleep_tracker.xml. - Dodaj właściwość
android:enableddo każdego przycisku. Właściwośćandroid:enabledto wartość logiczna, która wskazuje, czy przycisk jest włączony. (Przycisk aktywny można kliknąć, a nieaktywny – nie). Nadaj właściwości wartość zmiennej stanu, którą za chwilę zdefiniujesz.
start_button:
android:enabled="@{sleepTrackerViewModel.startButtonVisible}"stop_button:
android:enabled="@{sleepTrackerViewModel.stopButtonVisible}"clear_button:
android:enabled="@{sleepTrackerViewModel.clearButtonVisible}"- Otwórz
SleepTrackerViewModeli utwórz 3 odpowiednie zmienne. Przypisz każdej zmiennej przekształcenie, które ją testuje.
- Przycisk Start powinien być włączony, gdy
tonightma wartośćnull. - Przycisk Zatrzymaj powinien być włączony, gdy
tonightnie jest równenull. - Przycisk Wyczyść powinien być włączony tylko wtedy, gdy
nights, a tym samym baza danych, zawiera dane o nocach snu.
val startButtonVisible = Transformations.map(tonight) {
it == null
}
val stopButtonVisible = Transformations.map(tonight) {
it != null
}
val clearButtonVisible = Transformations.map(nights) {
it?.isNotEmpty()
}- Uruchom aplikację i wypróbuj przyciski.
Krok 2. Użyj paska powiadomień, aby powiadomić użytkownika
Gdy użytkownik wyczyści bazę danych, wyświetl potwierdzenie za pomocą widżetu Snackbar. Pasek powiadomień wyświetla krótki komunikat u dołu ekranu, który informuje o wyniku działania. Snackbar znika po upływie określonego czasu, po interakcji użytkownika w innym miejscu na ekranie lub po przesunięciu go przez użytkownika poza ekran.
Wyświetlanie paska informacyjnego jest zadaniem interfejsu i powinno odbywać się we fragmencie. Decyzja o wyświetleniu paska z informacją jest podejmowana w ViewModel. Aby skonfigurować i wywołać pasek z informacją o usunięciu danych, możesz użyć tej samej techniki co w przypadku wywoływania nawigacji.
- W sekcji
SleepTrackerViewModelutwórz zdarzenie hermetyzowane.
private var _showSnackbarEvent = MutableLiveData<Boolean>()
val showSnackBarEvent: LiveData<Boolean>
get() = _showSnackbarEvent- Następnie wdróż
doneShowingSnackbar().
fun doneShowingSnackbar() {
_showSnackbarEvent.value = false
}- W
SleepTrackerFragmentw sekcjionCreateView()dodaj obserwatora:
sleepTrackerViewModel.showSnackBarEvent.observe(this, Observer { })- W bloku obserwatora wyświetl pasek powiadomień i natychmiast zresetuj zdarzenie.
if (it == true) { // Observed state is true.
Snackbar.make(
activity!!.findViewById(android.R.id.content),
getString(R.string.cleared_message),
Snackbar.LENGTH_SHORT // How long to display the message.
).show()
sleepTrackerViewModel.doneShowingSnackbar()
}- W
SleepTrackerViewModelwywołaj zdarzenie w metodzieonClear(). Aby to zrobić, ustaw wartość zdarzenia natruew blokulaunch:
_showSnackbarEvent.value = true- Skompiluj i uruchom aplikację.
Projekt Android Studio: TrackMySleepQualityFinal
Wprowadzenie w tej aplikacji funkcji śledzenia jakości snu jest jak zagranie znanego utworu w nowej tonacji. Szczegóły się zmieniają, ale podstawowy wzorzec tego, co zostało zrobione w poprzednich ćwiczeniach w tej lekcji, pozostaje taki sam. Znajomość tych wzorców znacznie przyspiesza kodowanie, ponieważ możesz ponownie wykorzystywać kod z istniejących aplikacji. Oto niektóre wzorce użyte do tej pory w tym kursie:
- Utwórz
ViewModeliViewModelFactoryoraz skonfiguruj źródło danych. - Wywołaj nawigację. Aby rozdzielić zadania, umieść moduł obsługi kliknięć w modelu widoku, a nawigację we fragmencie.
- Używaj hermetyzacji z
LiveData, aby śledzić zmiany stanu i na nie reagować. - Używaj przekształceń z parametrem
LiveData. - Utwórz bazę danych singleton.
- Skonfiguruj coroutines do operacji na bazie danych.
Włączanie nawigacji
Możliwe ścieżki nawigacji między fragmentami określasz w pliku nawigacji. Nawigację z jednego fragmentu do drugiego można wywołać na kilka sposobów. Obejmują one:
- Zdefiniuj moduły obsługi
onClick, aby wywoływać nawigację do fragmentu docelowego. - Aby włączyć nawigację między fragmentami:
- Określ wartość
LiveData, aby rejestrować, czy ma nastąpić nawigacja. - Dołącz obserwatora do tej wartości
LiveData. - Kod zmienia tę wartość, gdy trzeba wywołać nawigację lub gdy nawigacja się zakończy.
Ustawianie atrybutu android:enabled
- Atrybut
android:enabledjest zdefiniowany wTextViewi dziedziczony przez wszystkie podklasy, w tymButton. - Atrybut
android:enabledokreśla, czyViewjest włączony. Znaczenie słowa „włączone” różni się w zależności od podklasy. Na przykład wyłączony elementEditTextuniemożliwia użytkownikowi edytowanie zawartego w nim tekstu, a wyłączony elementButtonuniemożliwia użytkownikowi kliknięcie przycisku. - Atrybut
enablednie jest taki sam jak atrybutvisibility. - Za pomocą map przekształceń możesz ustawić wartość atrybutu
enabledprzycisków na podstawie stanu innego obiektu lub zmiennej.
Inne kwestie omówione w tych ćwiczeniach z programowania:
- Aby wywołać powiadomienia dla użytkownika, możesz użyć tej samej techniki, której używasz do wywoływania nawigacji.
- Możesz użyć
Snackbar, aby powiadomić użytkownika.
Kurs Udacity:
Dokumentacja dla deweloperów aplikacji na Androida:
W tej sekcji znajdziesz listę możliwych zadań domowych dla uczniów, którzy wykonują ten moduł w ramach kursu prowadzonego przez instruktora. Nauczyciel musi:
- W razie potrzeby przypisz pracę domową.
- Poinformuj uczniów, jak przesyłać projekty.
- Oceń zadania domowe.
Instruktorzy mogą korzystać z tych sugestii w dowolnym zakresie i mogą zadawać inne zadania domowe, które uznają za odpowiednie.
Jeśli wykonujesz ten kurs samodzielnie, możesz użyć tych zadań domowych, aby sprawdzić swoją wiedzę.
Odpowiedz na te pytania
Pytanie 1
Jednym ze sposobów umożliwienia aplikacji wywoływania nawigacji z jednego fragmentu do drugiego jest użycie wartości LiveData, aby wskazać, czy wywołać nawigację.
Jakie kroki należy wykonać, aby użyć wartości LiveData o nazwie gotoBlueFragment do wywołania nawigacji z czerwonego fragmentu do niebieskiego? Zaznacz wszystkie pasujące opcje:
- W polu
ViewModelzdefiniuj wartośćLiveDatagotoBlueFragment. - W polu
RedFragmentsprawdź wartośćgotoBlueFragment. Zaimplementuj kodobserve{}, aby w odpowiednich przypadkach przejść doBlueFragment, a następnie zresetuj wartośćgotoBlueFragment, aby wskazać, że nawigacja została zakończona. - Upewnij się, że Twój kod ustawia zmienną
gotoBlueFragmentna wartość, która wywołuje nawigację, gdy aplikacja musi przejść zRedFragmentdoBlueFragment. - Upewnij się, że kod definiuje procedurę obsługi
onClickdla elementuView, który użytkownik klika, aby przejść do elementuBlueFragment, gdzie procedura obsługionClickobserwuje wartośćgoToBlueFragment.
Pytanie 2
Możesz zmienić, czy Button jest włączony (można go kliknąć), czy nie, za pomocą LiveData. Jak możesz się upewnić, że aplikacja zmieni przycisk UpdateNumber w taki sposób, aby:
- Przycisk jest włączony, jeśli wartość
myNumberjest większa niż 5. - Przycisk nie jest włączony, jeśli wartość
myNumberwynosi 5 lub mniej.
Załóżmy, że układ zawierający przycisk UpdateNumber zawiera zmienną <data> dla elementu NumbersViewModel, jak pokazano tutaj:
<data>
<variable
name="NumbersViewModel"
type="com.example.android.numbersapp.NumbersViewModel" />
</data>Załóżmy, że identyfikator przycisku w pliku układu jest taki:
android:id="@+id/update_number_button"
Co jeszcze musisz zrobić? Zaznacz wszystkie pasujące opcje.
- W klasie
NumbersViewModelzdefiniuj zmiennąLiveData,myNumber, która reprezentuje liczbę. Zdefiniuj też zmienną, której wartość jest ustawiana przez wywołanie funkcjiTransform.map()na zmiennejmyNumber. Zwraca ona wartość logiczną wskazującą, czy liczba jest większa od 5.
W plikuViewModeldodaj ten kod:
val myNumber: LiveData<Int>
val enableUpdateNumberButton = Transformations.map(myNumber) {
myNumber > 5
}- W układzie XML ustaw atrybut
android:enabledelementuupdate_number_button buttonnaNumberViewModel.enableUpdateNumbersButton.
android:enabled="@{NumbersViewModel.enableUpdateNumberButton}"- W elemencie
Fragment, który używa klasyNumbersViewModel, dodaj obserwatora do atrybutuenabledprzycisku.
W plikuFragmentdodaj ten kod:
// Observer for the enabled attribute
viewModel.enabled.observe(this, Observer<Boolean> { isEnabled ->
myNumber > 5
})- W pliku układu ustaw atrybut
android:enabledelementuupdate_number_button buttonna"Observable".
Przejdź do następnej lekcji:
Linki do innych ćwiczeń z tego kursu znajdziesz na stronie docelowej ćwiczeń z podstaw języka Kotlin na Androidzie.