Omówienie LiveData Należy do Android Jetpack.
LiveData
to obserwowalna klasa uchwytu danych. W odróżnieniu od zwykłego observable obiekt LiveData jest świadomy cyklu życia, co oznacza, że respektuje cykl życia innych komponentów aplikacji, takich jak aktywności, fragmenty czy usługi. Dzięki temu LiveData aktualizuje tylko obserwatorów komponentów aplikacji, które są w aktywności.
LiveData uznaje obserwatora, który jest reprezentowany przez klasę Observer
, za aktywny, jeśli jego cykl życia jest w stanie STARTED
lub RESUMED
. LiveData powiadamia o aktualizacjach tylko aktywnych obserwatorów. Nieaktywne obserwatorów zarejestrowane do obserwowania obiektów LiveData
nie są powiadamiane o zmianach.
Możesz zarejestrować obserwatora sparowanego z obiektem, który implementuje interfejs LifecycleOwner
. Ta relacja umożliwia usunięcie obserwatora, gdy stan odpowiadającego mu obiektu Lifecycle
zmieni się na DESTROYED
.
Jest to szczególnie przydatne w przypadku aktywności i fragmentów, ponieważ mogą one bezpiecznie obserwować obiekty LiveData
bez obaw o wycieki. Aktywności i fragmenty są natychmiast odsubskrybowane po zakończeniu ich cyklu życia.
Więcej informacji o korzystaniu z LiveData znajdziesz w artykule Praca z obiektmi LiveData.
Zalety korzystania z LiveData
Korzystanie z LiveData ma te zalety:
- Sprawdzanie, czy interfejs użytkownika jest zgodny ze stanem danych
- LiveData działa zgodnie ze wzorcem obserwatora. Usługa LiveData wysyła powiadomienia do obiektów
Observer
, gdy dane źródłowe ulegną zmianie. Aby zaktualizować interfejs za pomocą tych obiektówObserver
, możesz scalić kod. Dzięki temu nie musisz aktualizować interfejsu za każdym razem, gdy zmieniają się dane aplikacji, ponieważ obserwator robi to za Ciebie. - Brak wycieków pamięci
- Obserwatory są powiązani z obiektami
Lifecycle
i usuwają po sobie, gdy ich powiązany cykl życia zostanie zniszczony. - Brak awarii spowodowanych zatrzymanymi działaniami
- Jeśli cykl życia obserwatora jest nieaktywny, np. w przypadku aktywności w grupie wstecznej, nie otrzymuje on żadnych zdarzeń LiveData.
- Bez ręcznego zarządzania cyklem życia
- Komponenty interfejsu tylko obserwują odpowiednie dane i nie przerywają ani nie wznawiają obserwacji. LiveData automatycznie zarządza wszystkimi tymi funkcjami, ponieważ podczas obserwacji jest świadoma odpowiednich zmian stanu cyklu życia.
- Zawsze aktualne dane
- Jeśli cykl życia stanie się nieaktywny, po ponownym stanie się aktywnym otrzyma najnowsze dane. Na przykład aktywność, która była wykonywana w tle, otrzymuje najnowsze dane zaraz po tym, jak wraca na pierwszy plan.
- Właściwe zmiany konfiguracji
- Jeśli aktywność lub fragment zostanie utworzony ponownie z powodu zmiany konfiguracji, np. obracania urządzenia, natychmiast otrzyma najnowsze dostępne dane.
- Udostępnianie zasobów
- Możesz rozszerzyć obiekt
LiveData
, używając wzorca singleton, aby owijać usługi systemowe, tak aby można było je udostępniać w aplikacji. ObiektLiveData
łączy się z usługą systemową tylko raz, a następnie każdy obserwator, który potrzebuje zasobu, może obserwować obiektLiveData
. Więcej informacji znajdziesz w artykule Rozszerzanie danych LiveData.
Praca z obiektmi LiveData
Aby pracować z obiektmi LiveData
:
- Utwórz instancję
LiveData
, aby przechowywać określony typ danych. Zwykle odbywa się to w ramach klasyViewModel
. - Utwórz obiekt
Observer
, który definiuje metodęonChanged()
, która określa, co się stanie, gdy zmienią się dane przechowywane w obiekcieLiveData
. ObiektObserver
zwykle tworzysz w kontrolerze interfejsu użytkownika, takim jak aktywność lub fragment. Za pomocą metody
observe()
dołącz obiektObserver
do obiektuLiveData
. Metodaobserve()
przyjmuje obiektLifecycleOwner
. Dzięki temu obiektObserver
subskrybuje obiektLiveData
, aby otrzymywać powiadomienia o zmianach. ObiektObserver
zwykle dołączasz w kontrolerze interfejsu użytkownika, takim jak aktywność lub fragment.
Gdy zaktualizujesz wartość przechowywaną w obiekcie LiveData
, powoduje to wywołanie wszystkich zarejestrowanych obserwatorów, o ile dołączony obiekt LifecycleOwner
jest w stanie aktywnym.
LiveData umożliwia obserwatorom kontrolera interfejsu subskrybowanie aktualizacji. Gdy dane przechowywane przez obiekt LiveData
ulegną zmianie, interfejs użytkownika zostanie automatycznie zaktualizowany.
Tworzenie obiektów LiveData
LiveData to obiekt opakowujący, który może być używany z dowolnymi danymi, w tym z obiektami, które implementują interfejs Collections
, np. List
. Obiekt LiveData
jest zwykle przechowywany w obiekcie ViewModel
i jest dostępny za pomocą metody gettera, jak pokazano w tym przykładzie:
Kotlin
class NameViewModel : ViewModel() { // Create a LiveData with a String val currentName: MutableLiveData<String> by lazy { MutableLiveData<String>() } // Rest of the ViewModel... }
Java
public class NameViewModel extends ViewModel { // Create a LiveData with a String private MutableLiveData<String> currentName; public MutableLiveData<String> getCurrentName() { if (currentName == null) { currentName = new MutableLiveData<String>(); } return currentName; } // Rest of the ViewModel... }
Początkowo dane w obiekcie LiveData
nie są ustawione.
Więcej informacji o zaletach i użyciu klasy ViewModel
znajdziesz w przewodniku ViewModel.
Obserwowanie obiektów LiveData
W większości przypadków metoda onCreate()
komponentu aplikacji jest odpowiednim miejscem na rozpoczęcie obserwowania obiektu LiveData
z tych powodów:
- Aby mieć pewność, że system nie wykonuje zbędnych wywołań z metody
onResume()
aktywności lub fragmentu. - Aby mieć pewność, że aktywność lub fragment będzie mieć dane, które może wyświetlić, gdy stanie się aktywny. Gdy tylko komponent aplikacji znajdzie się w stanie
STARTED
, odbiera najnowszą wartość z obserwowanych obiektówLiveData
. Dzieje się tak tylko wtedy, gdy ustawiono obiektLiveData
, który ma być obserwowany.
Zazwyczaj LiveData dostarcza aktualizacje tylko wtedy, gdy zmieniają się dane, i tylko aktywnym obserwatorom. Wyjątkiem od tej zasady jest to, że obserwatorzy również otrzymują aktualizację, gdy stan ich konta zmieni się z nieaktywne na aktywne. Ponadto jeśli obserwator zmieni stan z nieaktywnego na aktywny po raz drugi, otrzyma aktualizację tylko wtedy, gdy wartość zmieniła się od ostatniego stanu aktywnego.
Poniższy przykładowy kod pokazuje, jak rozpocząć obserwowanie obiektu LiveData
:
Kotlin
class NameActivity : AppCompatActivity() { // Use the 'by viewModels()' Kotlin property delegate // from the activity-ktx artifact private val model: NameViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Other code to setup the activity... // Create the observer which updates the UI. val nameObserver = Observer<String> { newName -> // Update the UI, in this case, a TextView. nameTextView.text = newName } // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. model.currentName.observe(this, nameObserver) } }
Java
public class NameActivity extends AppCompatActivity { private NameViewModel model; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Other code to setup the activity... // Get the ViewModel. model = new ViewModelProvider(this).get(NameViewModel.class); // Create the observer which updates the UI. final Observer<String> nameObserver = new Observer<String>() { @Override public void onChanged(@Nullable final String newName) { // Update the UI, in this case, a TextView. nameTextView.setText(newName); } }; // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. model.getCurrentName().observe(this, nameObserver); } }
Po wywołaniu funkcji observe()
z parametrem nameObserver
natychmiast wywoływana jest funkcja onChanged()
, która przekazuje najnowszą wartość przechowywaną w tablicy mCurrentName
.
Jeśli obiekt LiveData
nie ma ustawionej wartości w elementach mCurrentName
, funkcja onChanged()
nie jest wywoływana.
Aktualizowanie obiektów LiveData
Usługa LiveData nie udostępnia publicznie metod aktualizowania przechowywanych danych. Klasa MutableLiveData
udostępnia publicznie metody setValue(T)
i postValue(T)
. Musisz ich używać, jeśli chcesz edytować wartość przechowywaną w obiekcie LiveData
. Zazwyczaj w sekcji ViewModel
używana jest funkcja MutableLiveData
, a obiekt ViewModel
udostępnia obserwatorom tylko niezmienne obiekty LiveData
.
Po skonfigurowaniu relacji obserwatora możesz zaktualizować wartość obiektu LiveData
, jak pokazano w następującym przykładzie, który uruchamia wszystkich obserwatorów, gdy użytkownik kliknie przycisk:
Kotlin
button.setOnClickListener { val anotherName = "John Doe" model.currentName.setValue(anotherName) }
Java
button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String anotherName = "John Doe"; model.getCurrentName().setValue(anotherName); } });
Wywołanie setValue(T)
w tym przykładzie powoduje, że obserwatorzy wywołują metody onChanged()
z wartością John Doe
. Przykład pokazuje naciśnięcie przycisku, ale funkcja setValue()
lub postValue()
może zostać wywołana w celu zaktualizowania mName
z różnych powodów, np. w odpowiedzi na żądanie sieci lub po zakończeniu wczytywania bazy danych. We wszystkich przypadkach wywołanie funkcji setValue()
lub postValue()
powoduje uruchomienie obserwatorów i zaktualizowanie interfejsu użytkownika.
Korzystanie z LiveData w Room
Biblioteka trwałości danych Room obsługuje zapytania obserwowalne, które zwracają obiekty LiveData
.
Zapytania obserwowalne są pisane jako część obiektu dostępu do bazy danych (DAO).
Gdy aktualizujesz bazę danych, Room generuje cały kod potrzebny do zaktualizowania obiektu LiveData
. Wygenerowany kod w razie potrzeby wykonuje zapytanie asynchronicznie na wątku w tle. Ten wzorzec jest przydatny do synchronizowania danych wyświetlanych w interfejsie z danymi zapisanymi w bazie danych. Więcej informacji o Room i DAO znajdziesz w przewodniku po bibliotece trwałości danych Room.
Korzystanie z coroutines w LiveData
LiveData
obsługuje coroutines w Kotlinie. Więcej informacji znajdziesz w artykule Używanie współbieżnych funkcji w Kotlinie z Android Architecture Components.
LiveData w architekturze aplikacji
LiveData
uwzględnia cykl życia, podążając za cyklem życia takich elementów jak aktywności i fragmenty. Użyj obiektu LiveData
, aby umożliwić komunikację między właścicielami cyklu życia a innymi obiektami o innej długości życia, takimi jak obiekty ViewModel
.
Głównym zadaniem obiektu ViewModel
jest wczytywanie danych związanych z interfejsem użytkownika i zarządzanie nimi, co czyni go idealnym kandydatem do przechowywania obiektów LiveData
. Utwórz obiekty LiveData
w komponencie ViewModel
i użyj ich do udostępniania stanu warstwie interfejsu użytkownika.
Aktywności i fragmenty nie powinny przechowywać instancji LiveData
, ponieważ ich zadaniem jest wyświetlanie danych, a nie przechowywanie stanu. Poza tym brak danych w akcjach i fragmentach ułatwia tworzenie testów jednostkowych.
Możesz mieć ochotę na pracę z obiektmi LiveData
w klasie warstwy danych, ale LiveData
nie jest przeznaczony do obsługi asynchronicznych strumieni danych. Mimo że do tego celu możesz użyć przekształceń LiveData
i funkcji MediatorLiveData
, takie podejście ma pewne wady: możliwość łączenia strumieni danych jest bardzo ograniczona, a wszystkie obiekty LiveData
(w tym te utworzone przez przekształcenia) są obserwowane w głównym wątku. Poniższy kod pokazuje, jak zablokowanie LiveData
w pętli Repository
może blokować główny wątek:
Kotlin
class UserRepository { // DON'T DO THIS! LiveData objects should not live in the repository. fun getUsers(): LiveData<List<User>> { ... } fun getNewPremiumUsers(): LiveData<List<User>> { return getUsers().map { users -> // This is an expensive call being made on the main thread and may // cause noticeable jank in the UI! users .filter { user -> user.isPremium } .filter { user -> val lastSyncedTime = dao.getLastSyncedTime() user.timeCreated > lastSyncedTime } } }
Java
class UserRepository { // DON'T DO THIS! LiveData objects should not live in the repository. LiveData<List<User>> getUsers() { ... } LiveData<List<User>> getNewPremiumUsers() { return Transformations.map(getUsers(), // This is an expensive call being made on the main thread and may cause // noticeable jank in the UI! users -> users.stream() .filter(User::isPremium) .filter(user -> user.getTimeCreated() > dao.getLastSyncedTime()) .collect(Collectors.toList())); } }
Jeśli chcesz używać strumieni danych w innych warstwach aplikacji, rozważ użycie Kotlin Flows, a potem ich konwersję na LiveData
w ViewModel
za pomocą asLiveData()
.
Więcej informacji o używaniu Kotlina Flow
z LiveData
znajdziesz w tym Codelab.
W przypadku baz kodu utworzonych w języku Java rozważ użycie wykonawców w połączeniu z wywołaniami zwrotnymi lub RxJava
.
Rozszerzanie danych na żywo
Z punktu widzenia usługi LiveData obserwator jest aktywny, jeśli jego cykl życia jest w stanie STARTED
lub RESUMED
. Poniższy przykładowy kod pokazuje, jak rozszerzyć klasę LiveData
:
Kotlin
class StockLiveData(symbol: String) : LiveData<BigDecimal>() { private val stockManager = StockManager(symbol) private val listener = { price: BigDecimal -> value = price } override fun onActive() { stockManager.requestPriceUpdates(listener) } override fun onInactive() { stockManager.removeUpdates(listener) } }
Java
public class StockLiveData extends LiveData<BigDecimal> { private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; public StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
Implementacja odbiornika cen w tym przykładzie obejmuje te ważne metody:
- Metoda
onActive()
jest wywoływana, gdy obiektLiveData
ma aktywnego obserwatora. Oznacza to, że musisz zacząć obserwować aktualizacje cen akcji z tej metody. - Metoda
onInactive()
jest wywoływana, gdy obiektLiveData
nie ma aktywnych obserwatorów. Ponieważ nie ma obserwatorów, nie ma powodu, aby pozostać w połączeniu z usługąStockManager
. - Metoda
setValue(T)
aktualizuje wartość instancjiLiveData
i powiadamia o tej zmianie wszystkich aktywnych obserwatorów.
Klasę StockLiveData
możesz używać w taki sposób:
Kotlin
public class MyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val myPriceListener: LiveData<BigDecimal> = ... myPriceListener.observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? -> // Update the UI. }) } }
Java
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); LiveData<BigDecimal> myPriceListener = ...; myPriceListener.observe(getViewLifecycleOwner(), price -> { // Update the UI. }); } }
Metoda observe()
przekazuje jako pierwszy argument LifecycleOwner
powiązany z widokiem fragmentu. Oznacza to, że ten obserwator jest powiązany z obiektem Lifecycle
powiązanym z właścicielem, co oznacza, że:
- Jeśli obiekt
Lifecycle
nie jest aktywny, obserwator nie jest wywoływany, nawet jeśli wartość się zmieni. - Po zniszczeniu obiektu
Lifecycle
obserwator zostanie automatycznie usunięty.
Obiekty LiveData
są świadome cyklu życia, co oznacza, że możesz je udostępniać między wieloma aktywnościami, fragmentami i usługami. Aby przykład był prostszy, klasę LiveData
możesz zaimplementować jako pojedynczy obiekt w ten sposób:
Kotlin
class StockLiveData(symbol: String) : LiveData<BigDecimal>() { private val stockManager: StockManager = StockManager(symbol) private val listener = { price: BigDecimal -> value = price } override fun onActive() { stockManager.requestPriceUpdates(listener) } override fun onInactive() { stockManager.removeUpdates(listener) } companion object { private lateinit var sInstance: StockLiveData @MainThread fun get(symbol: String): StockLiveData { sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol) return sInstance } } }
Java
public class StockLiveData extends LiveData<BigDecimal> { private static StockLiveData sInstance; private StockManager stockManager; private SimplePriceListener listener = new SimplePriceListener() { @Override public void onPriceChanged(BigDecimal price) { setValue(price); } }; @MainThread public static StockLiveData get(String symbol) { if (sInstance == null) { sInstance = new StockLiveData(symbol); } return sInstance; } private StockLiveData(String symbol) { stockManager = new StockManager(symbol); } @Override protected void onActive() { stockManager.requestPriceUpdates(listener); } @Override protected void onInactive() { stockManager.removeUpdates(listener); } }
Możesz go użyć w fragmentzie w ten sposób:
Kotlin
class MyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? -> // Update the UI. }) }
Java
public class MyFragment extends Fragment { @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> { // Update the UI. }); } }
Fragmenty i aktywności mogą obserwować instancję MyPriceListener
.
LiveData łączy się z usługą systemową tylko wtedy, gdy co najmniej 1 z nich jest widoczna i aktywna.
Przekształcanie danych LiveData
Możesz wprowadzić zmiany w wartości przechowywanej w obiekcie LiveData
przed wysłaniem go do obserwatorów. Może też być konieczne zwrócenie innego wystąpienia obiektu LiveData
na podstawie wartości innego. Pakiet Lifecycle
udostępnia klasę Transformations
, która zawiera metody pomocnicze obsługujące te scenariusze.
Transformations.map()
- Stosuje funkcję do wartości przechowywanej w obiekcie
LiveData
, a potem przekazuje wynik do dalszych elementów.
Kotlin
val userLiveData: LiveData<User> = UserLiveData() val userName: LiveData<String> = userLiveData.map { user -> "${user.name} ${user.lastName}" }
Java
LiveData<User> userLiveData = ...; LiveData<String> userName = Transformations.map(userLiveData, user -> { user.name + " " + user.lastName });
Transformations.switchMap()
- Podobnie jak
map()
, stosuje funkcję do wartości przechowywanej w obiekcieLiveData
, a następnie odwija i wysyła wynik do dalszego przetwarzania. Funkcja przekazana doswitchMap()
musi zwracać obiektLiveData
, jak pokazano w tym przykładzie:
Kotlin
private fun getUser(id: String): LiveData<User> { ... } val userId: LiveData<String> = ... val user = userId.switchMap { id -> getUser(id) }
Java
private LiveData<User> getUser(String id) { ...; } LiveData<String> userId = ...; LiveData<User> user = Transformations.switchMap(userId, id -> getUser(id) );
Metody przekształcania umożliwiają przenoszenie informacji w cyklu życia obserwatora. Przekształcenia nie są obliczane, chyba że obserwator obserwuje zwrócony obiekt LiveData
. Przekształcenia są obliczane płynnie, więc zachowanie związane z cyklem życia jest przekazywane do podklas w sposób domyślny bez konieczności korzystania z dodatkowych wywołań ani zależności.
Jeśli uważasz, że obiekt Lifecycle
powinien znajdować się w obiekcie ViewModel
, prawdopodobnie lepszym rozwiązaniem będzie użycie transformacji. Załóżmy na przykład, że masz komponent interfejsu użytkownika, który przyjmuje adres i zwraca kod pocztowy tego adresu. W przypadku tego komponentu możesz zastosować prostą funkcję ViewModel
, jak w tym przykładowym kodzie:
Kotlin
class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() { private fun getPostalCode(address: String): LiveData<String> { // DON'T DO THIS return repository.getPostCode(address) } }
Java
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; public MyViewModel(PostalCodeRepository repository) { this.repository = repository; } private LiveData<String> getPostalCode(String address) { // DON'T DO THIS return repository.getPostCode(address); } }
Komponent UI musi wtedy anulować rejestrację poprzedniego obiektu LiveData
i zarejestrować się w nowym wystąpieniu za każdym razem, gdy wywołuje funkcję getPostalCode()
. Ponadto jeśli komponent interfejsu użytkownika zostanie utworzony ponownie, spowoduje to wywołanie metody repository.getPostCode()
, a nie wykorzystanie wyniku poprzedniego wywołania.
Zamiast tego możesz zastosować wyszukiwanie kodu pocztowego jako przekształcenie danych wejściowych adresu, jak pokazano w tym przykładzie:
Kotlin
class MyViewModel(private val repository: PostalCodeRepository) : ViewModel() { private val addressInput = MutableLiveData<String>() val postalCode: LiveData<String> = addressInput.switchMap { address -> repository.getPostCode(address) } private fun setInput(address: String) { addressInput.value = address } }
Java
class MyViewModel extends ViewModel { private final PostalCodeRepository repository; private final MutableLiveData<String> addressInput = new MutableLiveData(); public final LiveData<String> postalCode = Transformations.switchMap(addressInput, (address) -> { return repository.getPostCode(address); }); public MyViewModel(PostalCodeRepository repository) { this.repository = repository } private void setInput(String address) { addressInput.setValue(address); } }
W tym przypadku pole postalCode
jest zdefiniowane jako przekształcenie pola addressInput
. Dopóki Twoja aplikacja ma aktywnego obserwatora powiązanego z polem postalCode
, jego wartość jest ponownie obliczana i pobierana za każdym razem, gdy zmienia się wartość pola addressInput
.
Ten mechanizm umożliwia tworzenie obiektów LiveData
na niższych poziomach aplikacji, które są obliczane leniwie na żądanie. Obiekt ViewModel
może łatwo uzyskać odwołania do obiektów LiveData
, a następnie zdefiniować reguły przekształcania na ich podstawie.
Tworzenie nowych przekształceń
Istnieje kilkanaście różnych transformacji, które mogą być przydatne w aplikacji, ale nie są one dostępne domyślnie. Aby zaimplementować własną transformację, możesz użyć klasy MediatorLiveData
, która nasłuchuje innych obiektów LiveData
i przetwarza emitowane przez nie zdarzenia. MediatorLiveData
prawidłowo rozpowszechnia swój stan do obiektu źródłowego LiveData
. Więcej informacji o tym wzorze znajdziesz w dokumentacji referencyjnej klasy Transformations
.
Scalanie kilku źródeł LiveData
MediatorLiveData
to podklasa klasy LiveData
, która umożliwia scalanie wielu źródeł LiveData. Obserwatory obiektów MediatorLiveData
są następnie uruchamiane, gdy nastąpi jakakolwiek zmiana w pierwotnych obiektach źródłowych LiveData.
Jeśli na przykład masz w interfejsie obiekt LiveData
, który można aktualizować z bazy danych lokalnej lub sieci, możesz dodać do obiektu MediatorLiveData
te źródła:
- Obiekt
LiveData
powiązany z danymi przechowywanymi w bazie danych. - Obiekt
LiveData
powiązany z danymi uzyskanymi z sieci.
Aby otrzymywać aktualizacje z obu źródeł, Twoja aktywność musi tylko obserwować obiekt MediatorLiveData
. Szczegółowy przykład znajdziesz w sekcji Załącznik: wyświetlanie stanu sieci w przewodniku Architektura aplikacji.
Dodatkowe materiały
Więcej informacji o klasie LiveData
znajdziesz w tych materiałach.
Próbki
- Sunflower, aplikacja demonstracyjna prezentująca sprawdzone metody dotyczące komponentów architektury
Ćwiczenia z programowania
- Android Room with a View (Java) (Kotlin)
- Dowiedz się więcej o zaawansowanych korobonach w Kotlin Flow i LiveData
Blogi
- ViewModels i LiveData: wzorce i nieprawidłowe rozwiązania
- LiveData poza ViewModel – wzorce reaktywne z wykorzystaniem funkcji Transformations i MediatorLiveData
- LiveData z SnackBar, nawigacją i innymi zdarzeniami (przypadek SingleLiveEvent)
Filmy
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Używanie współbieżnych funkcji Kotlina z komponentami uwzględniającymi cykl życia
- Zarządzanie cyklami życia za pomocą komponentów uwzględniających cykl życia
- Testowanie implementacji przełączania