Transformation.map ()
fun <X, Y> map(trigger: LiveData<X>, mapFunction: Function<X, Y> ): LiveData<Y>?
trigger- Die LiveData-Variable, die einmal geändert wurde, löst mapFunctiondie Ausführung aus.
mapFunction- Die Funktion, die aufgerufen werden soll, wenn eine Änderung an den triggerLiveData vorgenommen wird. Parameter X ist eine Referenz auf trigger(via it). Die Funktion gibt ein Ergebnis des angegebenen Typs Y zurück, das letztendlich map()als LiveData-Objekt zurückgegeben wird.
Verwenden map()Sie diese Option, wenn Sie eine Operation (über mapFunction) ausführen möchten, wenn sich die triggerLiveData-Variable ändert. map()gibt ein LiveData-Objekt zurück, das beim Aufruf beachtet werden mapFunctionsollte.
Beispiel:
Nehmen Sie eine einfache Liste von Bowlernamen an, deren Durchschnitt und Durchschnitt mit Handicap:
data class Bowler(val name:String, val average:Int, var avgWHDCP:Int)
var bowlers = listOf<Bowler>(Bowler("Steve", 150,150), Bowler ("Tom", 210, 210))
Angenommen, eine MutableLiveData IntVariable enthält einen Handicap-Inkrementwert. Wenn sich dieser Wert ändert, müssen avgWHDCPalle Bowler in der Liste neu berechnet werden. Anfangs wird es auf Null gesetzt.
var newHDCP:MutableLiveData<Int> = MutableLiveData(0)
Erstellen Sie eine Variable, die aufruft Tranformation.map(). Das erste Argument ist newHDCP. Das zweite Argument ist die Funktion, die bei newHDCPÄnderungen aufgerufen werden soll . In diesem Beispiel durchläuft die Funktion alle Bowlerobjekte, berechnet die neue avgWHDCPfür jeden Bowler in der Bowlerliste und gibt das Ergebnis als beobachtbare Liste von LiveData Bowler-Objekten zurück. Beachten Sie, dass in diesem Beispiel die ursprüngliche Nicht-LiveData-Liste der Bowler und die zurückgegebene Liste der Bowler denselben Wert widerspiegeln, da sie auf denselben Datenspeicher verweisen. Das Ergebnis der Funktion ist jedoch beobachtbar. Die ursprüngliche Liste der Bowler ist nicht so, wie sie nicht als LiveData eingerichtet wurde.
var updatedBowlers: LiveData<List<Bowler>> = Transformations.map(newHDCP) {
bowlers.forEach { bowler ->
bowler.avgWHDCP = bowler.average + it
}
return@map bowlers
}
Fügen Sie irgendwo in Ihrem Code eine Methode zum Aktualisieren hinzu newHDCP. In meinem Beispiel wird beim Klicken auf ein Optionsfeld newHDCPetwas geändert, und der Prozess wird ausgelöst, um die in angegebene Funktion aufzurufenTransformations.map()
rbUpdateBy20.setOnCheckedChangeListener { _, isChecked ->
viewModel.bowlingBallObject.newHDCP.value = 20
}
Schließlich funktioniert dies alles nur, wenn updatedBowlerses beachtet wird. Dies würde in Ihrer Aktivität oder Fragment in einer Methode wie platziertOnViewCreated()
viewModel.updatedBowlers.observe(viewLifecycleOwner, Observer { bowler ->
if (viewLifecycleOwner.lifecycle.currentState == Lifecycle.State.RESUMED) {
refreshRecycler()
}
})
Wenn Sie etwas prägnanter werden möchten und wirklich keinen Live-Verweis benötigen updatedBowlers, können Sie Folgendes updateBowlersmit dem Beobachter kombinieren :
Transformations.map(viewModel.newHDCP) {
viewModel.bowlers.forEach { bowler ->
bowler.avgWHDCP = bowler.average + it
}
return@map viewModel.bowlers
}.observe(viewLifecycleOwner, Observer { bowler ->
if (viewLifecycleOwner.lifecycle.currentState == Lifecycle.State.RESUMED) {
refreshRecycler()
}
})
Und das war's auch schon. Jedes Mal, wenn Sie den Wert von ändern newHDCP, wird die in angegebene Funktion Transformation.map()aufgerufen, das Bowler-Objekt mit dem neu berechneten transformiert avgWHDCPund ein LiveData-Objekt von zurückgegebenList<Bowler>
Transformation.switchMap ()
fun <X, Y> switchMap(source: LiveData<X>, switchMapFunction: Function<X, LiveData<Y>!>): LiveData<Y>
source- Die LiveData-Variable, die nach dem Ändern die switchMapFunctionAusführung auslöst .
switchMapFunction- Die Funktion, die aufgerufen werden soll, wenn eine Änderung an den LiveData-Quellen vorgenommen wird. Parameter X bezieht sich auf dasselbe Quellobjekt (via it). Die switchMapFunctionFunktion MUSS ein LiveData-Ergebnis zurückgeben, das effektiv über zurückgegeben wird Transformation.switchMap(). Im Wesentlichen können Sie so eine Referenz eines LiveData-Containerobjekts gegen eine andere austauschen.
Verwenden switchMap()Sie diese Option, wenn Sie eine Variable haben, die auf ein LiveData-Objekt verweist, und diese Variable auf eine andere umschalten oder auf andere Weise den vorhandenen LiveData-Container aktualisieren möchten. Dies ist beispielsweise nützlich, wenn Ihre LiveData-Variable auf einen Datenbankdatenspeicher verweist und Sie eine Anforderung mit verschiedenen Parametern durchführen möchten. switchMapMit dieser Option können Sie die Abfrage erneut ausführen und durch neue LiveData-Ergebnisse ersetzen.
Beispiel :
Angenommen, ein Datenbank-Repository mit einer Reihe von Bowlingkugel-Abfragen aus einer BowlingBall-DAO-Tabelle:
private val repository = BowlingBallRepository(application)
Und ich möchte eine Abfrage ausführen, die aktive oder inaktive Bowlingkugeln abruft, je nachdem, was der Benutzer angibt. Über die Benutzeroberfläche kann der Benutzer aktiv oder inaktiv auswählen, sodass meine Abfrage beide verarbeiten muss. Also erstelle ich eine MutableLiveDataVariable, die einen aktiven oder inaktiven Status hat. In diesem Beispiel ist standardmäßig 'A' für aktiv.
var activeFlag:MutableLiveData<String> = MutableLiveData(“A”)
Jetzt benötigen wir eine LiveData-Variable, die das Ergebnis meiner Abfrage enthält, um alle Bowlingkugeln eines bestimmten Status abzurufen. Also erstelle ich eine Variable namens allBowlingBallstype LiveData<List<BowlingBallTable>>?und weise sie zu Transformation.switchMap. Ich übergebe der switchMapFunktion die activeFlagVariable sowie eine Lambda-Funktion, die dieselbe activeFlagVariable (via it) empfängt, und die Funktion ruft eine Abfrage im DB-Repository auf, um alle Bowlingkugeln mit dem übergebenen Status erneut abzurufen. Das LiveData-Ergebnis der Lambda-Funktion durchläuft die switchMapMethode und wird neu zugewiesen allBowlingBalls.
private var allBowlingBalls: LiveData<List<BowlingBallTable>>? = Transformations.switchMap(activeFlag) {repository.getAllBalls(it)}
Ich brauche einen Weg, um eine Aktualisierung von auszulösen allBowlibgBalls. Dies wird wiederum bei activeFlagÄnderungen durchgeführt. Fügen Sie irgendwo in Ihrem Code eine zu aktualisierende Funktion hinzu activeFlag. In meinem Beispiel wird beim Klicken auf ein Optionsfeld activeFlagetwas geändert, und der Prozess wird ausgelöst, um die in angegebene Funktion aufzurufenTransformations.switchMap()
rbActive.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
viewModel.activeFlag.value = ActiveInactive.ACTIVE.flag
refreshRecycler()
}
}
Schließlich funktioniert dies alles nur, wenn allBowlingBalls beobachtet wird. Erstellen Sie also zuerst eine Funktion zum Abrufen von allBowlingBalls:
fun getAllBowlingBalls():LiveData<List<BowlingBallTable>>? {
return allBowlingBalls
}
Dann setzen Sie einen Beobachter auf getAllBowlingBalls():
viewModel.getAllBowlingBalls()?.observe(viewLifecycleOwner, Observer { balls ->
if (viewLifecycleOwner.lifecycle.currentState == Lifecycle.State.RESUMED) {
refreshRecycler()
}
})
Und das war's. Jedes Mal activeFlag, wenn sich Änderungen ergeben, allBowlingBallswird es mit einem Aufruf des Repositorys aktualisiert und das onChangeEreignis des Beobachters allBowlingBallswird ausgelöst. Eine einfache Technik zum Aufbau einer dynamischen Suchmaschine.