LiveData-Übersicht Teil von Android Jetpack
LiveData
ist eine beobachtbare Dateninhaberklasse. Im Gegensatz zu einem regulären beobachtbaren Element berücksichtigt LiveData den Lebenszyklus. Das bedeutet, dass der Lebenszyklus anderer Anwendungskomponenten wie Aktivitäten, Fragmente oder Dienste berücksichtigt wird. Dadurch wird sichergestellt, dass LiveData nur Beobachter von App-Komponenten aktualisiert, die sich in einem aktiven Lebenszyklus befinden.
Für LiveData wird ein Beobachter, der durch die Klasse Observer
dargestellt wird, als aktiv betrachtet, wenn sein Lebenszyklus den Status STARTED
oder RESUMED
hat. LiveData benachrichtigt nur aktive Beobachter über Aktualisierungen. Inaktive Beobachter, die für die Überwachung von LiveData
-Objekten registriert sind, werden nicht über Änderungen benachrichtigt.
Sie können einen Beobachter registrieren, der mit einem Objekt gekoppelt ist, das die LifecycleOwner
-Schnittstelle implementiert. Durch diese Beziehung kann der Beobachter entfernt werden, wenn sich der Status des entsprechenden Lifecycle
-Objekts in DESTROYED
ändert.
Dies ist besonders bei Aktivitäten und Fragmenten nützlich, da diese LiveData
-Objekte sicher beobachten können und sich keine Gedanken über Datenlecks machen müssen. Aktivitäten und Fragmente werden sofort abgemeldet, wenn ihre Lebenszyklen gelöscht werden.
Weitere Informationen zur Verwendung von LiveData finden Sie unter Mit LiveData-Objekten arbeiten.
Die Vorteile von LiveData
Die Verwendung von LiveData bietet folgende Vorteile:
- Sorgt dafür, dass die UI dem Datenstatus entspricht
- LiveData folgt dem Muster des Beobachters. LiveData benachrichtigt
Observer
-Objekte, wenn zugrunde liegende Daten geändert werden. In diesenObserver
-Objekten können Sie Ihren Code konsolidieren, um die UI zu aktualisieren. Auf diese Weise müssen Sie die UI nicht jedes Mal aktualisieren, wenn sich die Anwendungsdaten ändern, da das der Beobachter für Sie übernimmt. - Keine Speicherlecks
- Beobachter sind an
Lifecycle
-Objekte gebunden und bereinigen diese nach dem Löschen des zugehörigen Lebenszyklus. - Keine Abstürze aufgrund angehaltener Aktivitäten
- Wenn der Lebenszyklus des Beobachters inaktiv ist, z. B. bei einer Aktivität im Back-Stack, empfängt er keine LiveData-Ereignisse.
- Keine manuelle Lebenszyklusbehandlung mehr
- UI-Komponenten erfassen lediglich relevante Daten und werden nicht unterbrochen oder fortgesetzt. LiveData verwaltet all das automatisch, da die relevanten Statusänderungen des Lebenszyklus während der Beobachtung berücksichtigt werden.
- Immer aktuelle Daten
- Wenn ein Lebenszyklus inaktiv wird, erhält er die neuesten Daten, sobald er wieder aktiv wird. Beispielsweise erhält eine Aktivität, die im Hintergrund ausgeführt wurde, die neuesten Daten direkt nach der Rückkehr in den Vordergrund.
- Richtige Konfigurationsänderungen
- Wenn eine Aktivität oder ein Fragment aufgrund einer Konfigurationsänderung neu erstellt wird, z. B. bei einer Geräterotation, werden sofort die neuesten verfügbaren Daten empfangen.
- Ressourcen freigeben
- Sie können ein
LiveData
-Objekt mit dem Singleton-Muster erweitern, um Systemdienste zu umschließen und in Ihrer Anwendung freigeben zu können. DasLiveData
-Objekt stellt einmalig eine Verbindung zum Systemdienst her. Jeder Beobachter, der die Ressource benötigt, kann dann einfach dasLiveData
-Objekt beobachten. Weitere Informationen finden Sie unter LiveData erweitern.
Mit LiveData-Objekten arbeiten
So arbeiten Sie mit LiveData
-Objekten:
- Erstellen Sie eine Instanz von
LiveData
für einen bestimmten Datentyp. Dies erfolgt normalerweise innerhalb der KlasseViewModel
. - Erstellen Sie ein
Observer
-Objekt, mit dem die MethodeonChanged()
definiert wird, die steuert, was passiert, wenn sich die auf „Hold“ gesetzten Daten desLiveData
-Objekts ändern. Normalerweise erstellen Sie einObserver
-Objekt in einem UI-Controller, z. B. eine Aktivität oder ein Fragment. Hängen Sie das Objekt
Observer
mit der Methodeobserve()
an das ObjektLiveData
an. Für die Methodeobserve()
wird einLifecycleOwner
-Objekt verwendet. Dadurch wird das ObjektObserver
für das ObjektLiveData
abonniert, sodass es über Änderungen benachrichtigt wird. Normalerweise hängen Sie dasObserver
-Objekt in einem UI-Controller an, z. B. in einer Aktivität oder einem Fragment.
Wenn Sie den im Objekt LiveData
gespeicherten Wert aktualisieren, werden alle registrierten Beobachter ausgelöst, solange das angehängte LifecycleOwner
-Element aktiv ist.
Mit LiveData können UI-Controller-Beobachter Updates abonnieren. Wenn sich die Daten des LiveData
-Objekts ändern, wird die UI automatisch entsprechend aktualisiert.
LiveData-Objekte erstellen
LiveData ist ein Wrapper, der mit allen Daten verwendet werden kann, einschließlich Objekten, die Collections
implementieren, z. B. List
. Ein LiveData
-Objekt wird normalerweise in einem ViewModel
-Objekt gespeichert und über eine Getter-Methode aufgerufen, wie im folgenden Beispiel gezeigt:
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... }
Anfangs sind die Daten in einem LiveData
-Objekt nicht festgelegt.
Weitere Informationen zu den Vorteilen und zur Nutzung der ViewModel
-Klasse finden Sie in der Anleitung zu ViewModel.
LiveData-Objekte beobachten
In den meisten Fällen ist die Methode onCreate()
einer App-Komponente aus den folgenden Gründen der richtige Ort, um ein LiveData
-Objekt zu beobachten:
- Damit das System keine redundanten Aufrufe über die Methode
onResume()
einer Aktivität oder eines Fragments sendet. - Um sicherzustellen, dass die Aktivität oder das Fragment Daten hat, die angezeigt werden können, sobald sie aktiv werden. Sobald eine App-Komponente den Status
STARTED
hat, erhält sie den neuesten Wert von den von ihr beobachtetenLiveData
-Objekten. Dies geschieht nur, wenn das zu beobachtendeLiveData
-Objekt festgelegt wurde.
Im Allgemeinen liefert LiveData Aktualisierungen nur dann, wenn sich Daten ändern, und nur an aktive Beobachter. Eine Ausnahme von diesem Verhalten besteht darin, dass Beobachter auch ein Update erhalten, wenn sie von einem inaktiven in einen aktiven Status wechseln. Wenn der Beobachter außerdem ein zweites Mal von „Inaktiv“ zu „Aktiv“ wechselt, erhält er nur dann eine Aktualisierung, wenn sich der Wert seit der letzten Aktivierung geändert hat.
Der folgende Beispielcode zeigt, wie ein LiveData
-Objekt beobachtet wird:
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); } }
Nachdem observe()
mit nameObserver
als Parameter aufgerufen wurde, wird onChanged()
sofort aufgerufen, wodurch der neueste Wert bereitgestellt wird, der in mCurrentName
gespeichert ist.
Wenn das LiveData
-Objekt keinen Wert in mCurrentName
festgelegt hat, wird onChanged()
nicht aufgerufen.
LiveData-Objekte aktualisieren
LiveData hat keine öffentlich verfügbaren Methoden zum Aktualisieren der gespeicherten Daten. Die Klasse MutableLiveData
macht die Methoden setValue(T)
und postValue(T)
öffentlich verfügbar. Sie müssen diese verwenden, wenn Sie den in einem LiveData
-Objekt gespeicherten Wert bearbeiten müssen. Normalerweise wird MutableLiveData
in der ViewModel
verwendet. Dann stellt ViewModel
den Beobachtern nur unveränderliche LiveData
-Objekte zur Verfügung.
Nachdem Sie die Beobachterbeziehung eingerichtet haben, können Sie den Wert des LiveData
-Objekts aktualisieren, wie im folgenden Beispiel veranschaulicht, das alle Beobachter auslöst, wenn der Nutzer auf eine Schaltfläche tippt:
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); } });
Wenn im Beispiel setValue(T)
aufgerufen wird, rufen die Beobachter ihre onChanged()
-Methoden mit dem Wert John Doe
auf. Das Beispiel zeigt ein Betätigen einer Taste. Es kann aber aus verschiedenen Gründen die Methode setValue()
oder postValue()
aufgerufen werden, um mName
zu aktualisieren, z. B. als Antwort auf eine Netzwerkanfrage oder den Abschluss einer Datenbanklast. Durch den Aufruf von setValue()
oder postValue()
werden in allen Fällen Beobachter ausgelöst und die UI aktualisiert.
LiveData mit Raum verwenden
Die Persistenzbibliothek Room unterstützt beobachtbare Abfragen, die LiveData
-Objekte zurückgeben.
Beobachtbare Abfragen werden als Teil eines Database Access Objects (DAO) geschrieben.
Room generiert den gesamten erforderlichen Code, um das LiveData
-Objekt beim Aktualisieren einer Datenbank zu aktualisieren. Der generierte Code führt die Abfrage bei Bedarf asynchron in einem Hintergrundthread aus. Dieses Muster ist nützlich, um die in einer UI angezeigten Daten mit den in einer Datenbank gespeicherten Daten synchron zu halten. Weitere Informationen zu Room und DAOs finden Sie im Leitfaden zur persistenten Raumbibliothek.
Koroutinen mit LiveData verwenden
LiveData
unterstützt Kotlin-Koroutinen. Weitere Informationen finden Sie unter Kotlin-Koroutinen mit Android-Architekturkomponenten verwenden.
LiveData in der Architektur einer App
LiveData
berücksichtigt den Lebenszyklus und folgt dem Lebenszyklus von Entitäten, z. B. Aktivitäten und Fragmenten. Verwenden Sie LiveData
, um zwischen diesen Lebenszyklusinhabern und anderen Objekten mit einer anderen Lebensdauer zu kommunizieren, z. B. ViewModel
-Objekte.
Die Hauptaufgabe von ViewModel
besteht darin, UI-bezogene Daten zu laden und zu verwalten. Sie eignet sich daher hervorragend zum Speichern von LiveData
-Objekten. Erstellen Sie LiveData
-Objekte in der Datei ViewModel
und stellen Sie damit den Status für die UI-Ebene bereit.
Aktivitäten und Fragmente sollten keine LiveData
-Instanzen enthalten, da sie die Rolle der Anzeige von Daten und nicht des Hold-Status haben. Außerdem wird das Schreiben von Einheitentests vereinfacht, wenn Aktivitäten und Fragmente keine Daten speichern.
Es mag verlockend sein, LiveData
-Objekte in der Datenschichtklasse zu verwenden. LiveData
ist jedoch nicht für asynchrone Datenstreams ausgelegt. Sie können zwar LiveData
-Transformationen und MediatorLiveData
verwenden, um dies zu erreichen, dieser Ansatz hat jedoch Nachteile: Die Möglichkeit, Datenströme zu kombinieren, ist sehr begrenzt und alle LiveData
-Objekte (einschließlich der durch Transformationen erstellten) werden im Hauptthread beobachtet. Der folgende Code zeigt ein Beispiel dafür, wie das Halten einer LiveData
in der Repository
den Hauptthread blockieren kann:
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())); } }
Wenn Sie Datenstreams in anderen Ebenen Ihrer App verwenden müssen, sollten Sie Kotlin-Abläufe verwenden und sie dann im ViewModel
mit asLiveData()
in LiveData
konvertieren.
Weitere Informationen zur Verwendung von Kotlin Flow
mit LiveData
findest du in diesem Codelab.
Ziehen Sie für Codebasis, die mit Java erstellt wurde, Executors in Verbindung mit Callbacks oder RxJava
in Betracht.
LiveData erweitern
Für LiveData gilt ein Beobachter als aktiv, wenn sich der Lebenszyklus des Beobachters entweder im Status STARTED
oder RESUMED
befindet. Der folgende Beispielcode zeigt, wie die Klasse LiveData
erweitert werden kann:
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); } }
Die Implementierung des Preis-Listeners in diesem Beispiel umfasst die folgenden wichtigen Methoden:
- Die Methode
onActive()
wird aufgerufen, wenn dasLiveData
-Objekt einen aktiven Beobachter hat. Das bedeutet, dass Sie mit dieser Methode die Aktualisierungen des Aktienkurses beobachten müssen. - Die Methode
onInactive()
wird aufgerufen, wenn dasLiveData
-Objekt keine aktiven Beobachter hat. Da keine Beobachter zuhören, gibt es keinen Grund, mit dem DienstStockManager
verbunden zu bleiben. - Die Methode
setValue(T)
aktualisiert den Wert derLiveData
-Instanz und benachrichtigt alle aktiven Beobachter über die Änderung.
Sie können die Klasse StockLiveData
so verwenden:
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. }); } }
Die Methode observe()
übergibt den LifecycleOwner
, der mit der Ansicht des Fragments verknüpft ist, als erstes Argument. Dadurch ist dieser Beobachter an das Objekt Lifecycle
gebunden, das mit dem Inhaber verknüpft ist. Das bedeutet:
- Wenn das
Lifecycle
-Objekt nicht aktiv ist, wird der Beobachter auch dann nicht aufgerufen, wenn sich der Wert ändert. - Nach dem Löschen des
Lifecycle
-Objekts wird der Beobachter automatisch entfernt.
Da LiveData
-Objekte den Lebenszyklus berücksichtigen, können sie von mehreren Aktivitäten, Fragmenten und Diensten gemeinsam verwendet werden. Um das Beispiel einfach zu halten, können Sie die Klasse LiveData
als Singleton implementieren:
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); } }
Im Fragment können Sie sie so verwenden:
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. }); } }
Mehrere Fragmente und Aktivitäten können die MyPriceListener
-Instanz beobachten.
LiveData stellt nur dann eine Verbindung zum Systemdienst her, wenn einer oder mehrere davon sichtbar und aktiv sind.
LiveData transformieren
Möglicherweise müssen Sie den in einem LiveData
-Objekt gespeicherten Wert ändern, bevor Sie ihn an die Beobachter senden, oder Sie müssen eine andere LiveData
-Instanz basierend auf dem Wert einer anderen Instanz zurückgeben. Das Paket Lifecycle
stellt die Klasse Transformations
mit Hilfsmethoden bereit, die diese Szenarien unterstützen.
Transformations.map()
- Wendet eine Funktion auf den im Objekt
LiveData
gespeicherten Wert an und gibt das Ergebnis nachgelagert weiter.
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()
- Ähnlich wie bei
map()
wird eine Funktion auf den im ObjektLiveData
gespeicherten Wert angewendet. Das Ergebnis wird entpackt und nachgelagert. Die answitchMap()
übergebene Funktion muss einLiveData
-Objekt zurückgeben, wie im folgenden Beispiel gezeigt:
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) );
Sie können Transformationsmethoden verwenden, um Informationen über den Lebenszyklus des Beobachters zu übertragen. Die Transformationen werden nur berechnet, wenn ein Beobachter das zurückgegebene LiveData
-Objekt überwacht. Da die Transformationen verzögert berechnet werden, wird lebenszyklusbezogenes Verhalten implizit übergeben, ohne dass zusätzliche explizite Aufrufe oder Abhängigkeiten erforderlich sind.
Wenn Sie der Meinung sind, dass Sie ein Lifecycle
-Objekt in einem ViewModel
-Objekt benötigen, ist eine Transformation wahrscheinlich die bessere Lösung. Angenommen, Sie haben eine UI-Komponente, die eine Adresse akzeptiert und die Postleitzahl für diese Adresse zurückgibt. Sie können den einfachen ViewModel
für diese Komponente implementieren, wie im folgenden Beispielcode veranschaulicht:
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); } }
Die UI-Komponente muss dann jedes Mal, wenn sie getPostalCode()
aufruft, ihre Registrierung beim vorherigen LiveData
-Objekt aufheben und sie bei der neuen Instanz registrieren. Wird die UI-Komponente neu erstellt, löst sie außerdem einen weiteren Aufruf der Methode repository.getPostCode()
aus, anstatt das Ergebnis des vorherigen Aufrufs zu verwenden.
Stattdessen können Sie die Postleitzahlsuche als Transformation der Adresseingabe implementieren, wie im folgenden Beispiel gezeigt:
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); } }
In diesem Fall ist das Feld postalCode
als Transformation von addressInput
definiert. Wenn Ihre Anwendung einen aktiven Beobachter mit dem Feld postalCode
verknüpft hat, wird der Wert des Felds neu berechnet und abgerufen, wenn sich addressInput
ändert.
Dieser Mechanismus ermöglicht es niedrigeren Ebenen der App, LiveData
-Objekte zu erstellen, die bei Bedarf verzögert berechnet werden. Ein ViewModel
-Objekt kann ganz einfach Verweise auf LiveData
-Objekte erhalten und darauf aufbauende Transformationsregeln definieren.
Neue Transformationen erstellen
Es gibt Dutzende verschiedene Transformationen, die in Ihrer Anwendung nützlich sein können, aber nicht standardmäßig bereitgestellt werden. Wenn Sie Ihre eigene Transformation implementieren möchten, können Sie die Klasse MediatorLiveData
verwenden, die andere LiveData
-Objekte überwacht und von ihnen ausgegebene Ereignisse verarbeitet. MediatorLiveData
leitet seinen Status korrekt an das LiveData
-Quellobjekt weiter. Weitere Informationen zu diesem Muster finden Sie in der Referenzdokumentation zur Klasse Transformations
.
Mehrere LiveData-Quellen zusammenführen
MediatorLiveData
ist eine abgeleitete Klasse von LiveData
, mit der Sie mehrere LiveData-Quellen zusammenführen können. Beobachter von MediatorLiveData
-Objekten werden dann immer dann ausgelöst, wenn sich die ursprünglichen LiveData-Quellobjekte ändern.
Wenn Sie beispielsweise ein LiveData
-Objekt in Ihrer UI haben, das aus einer lokalen Datenbank oder einem Netzwerk aktualisiert werden kann, können Sie dem MediatorLiveData
-Objekt die folgenden Quellen hinzufügen:
- Ein
LiveData
-Objekt, das den in der Datenbank gespeicherten Daten zugeordnet ist. - Ein
LiveData
-Objekt, das den Daten zugeordnet ist, auf die aus dem Netzwerk zugegriffen wird.
Ihre Aktivität muss nur das Objekt MediatorLiveData
beobachten, um Updates aus beiden Quellen zu erhalten. Ein detailliertes Beispiel finden Sie im Abschnitt Zusatz: Netzwerkstatus verfügbar machen des Leitfadens zur Anwendungsarchitektur.
Weitere Informationen
Weitere Informationen zur Klasse LiveData
finden Sie in den folgenden Ressourcen.
Produktproben
- Sunflower, eine Demo-App, die Best Practices für Architekturkomponenten zeigt
- Basisbeispiel für Android-Architekturkomponenten
Codelabs
- Android Room mit einer Ansicht (Java) (Kotlin)
- Mit Kotlin-Flow und LiveData erweiterte Koroutinen kennenlernen
Blogs
- ViewModels und LiveData: Patterns + AntiPatterns
- LiveData über das ViewModel hinaus – reaktive Muster mit Transformationen und MediatorLiveData
- LiveData mit Snackbar, Navigation und anderen Ereignissen (Fall „SingleLiveEvent“)
Videos
Empfehlungen für dich
- Hinweis: Der Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
- Kotlin-Koroutinen mit Komponenten verwenden, die den Lebenszyklus berücksichtigen
- Lebenszyklen mit lebenszyklusbewussten Komponenten handhaben
- Auslagerungsimplementierung testen