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 mapFunction
die Ausführung aus.
mapFunction
- Die Funktion, die aufgerufen werden soll, wenn eine Änderung an den trigger
LiveData 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 trigger
LiveData-Variable ändert. map()
gibt ein LiveData-Objekt zurück, das beim Aufruf beachtet werden mapFunction
sollte.
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
Int
Variable enthält einen Handicap-Inkrementwert. Wenn sich dieser Wert ändert, müssen avgWHDCP
alle 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 avgWHDCP
fü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 newHDCP
etwas 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 updatedBowlers
es 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 updateBowlers
mit 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 avgWHDCP
und 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 switchMapFunction
Ausfü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 switchMapFunction
Funktion 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. switchMap
Mit 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 MutableLiveData
Variable, 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 allBowlingBalls
type LiveData<List<BowlingBallTable>>?
und weise sie zu Transformation.switchMap
. Ich übergebe der switchMap
Funktion die activeFlag
Variable sowie eine Lambda-Funktion, die dieselbe activeFlag
Variable (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 switchMap
Methode 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 activeFlag
etwas 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, allBowlingBalls
wird es mit einem Aufruf des Repositorys aktualisiert und das onChange
Ereignis des Beobachters allBowlingBalls
wird ausgelöst. Eine einfache Technik zum Aufbau einer dynamischen Suchmaschine.