0

Ich verwende jetzt die neuesten Android-Architekturkomponenten und insbesondere das ViewModel und LiveData.LiveData - Verwenden von SingleLiveEvent mit Transformationen

Ich bin in einem Fall, in dem SingleLiveEvent vorgeschlagen here ist relevant, d. H. Ich gebe einen Fehler zurück und ich möchte eine Warnung nur einmal anzeigen. Bevor ich einen Wert für die Aktivität ausgeben kann, muss ich meinen Fehler einem geeigneteren Objekt für die Ansicht zuordnen. Ich benutze eine Transformation dafür.

Also am Ende habe ich ein Ansichtsmodell, das wie folgt aussieht:

public LiveData<ViewState> getStateForView() { 
    final LiveData<NetworkState> liveState = myRepository.getState(); 
    return Transformations.map(liveState, myMapper::map); 
} 

Wo in meinem Repository ich ein SingleLiveEvent bin mit:

public LiveData<NetworkState> getState() { 
    myNetworkState = new SingleLiveEvent<>(); 
    return myNetworkState; 
} 

Diese ziemlich gut funktioniert, aber ich merke, dass mein Ereignis wird nicht die ganze Zeit weitergegeben, wenn sich die Ausrichtung mehrmals ändert. Beim Debuggen, habe ich festgestellt, dass es keine Symmetrie zwischen dem Beobachter Registrierung und Entfernung:

  • zum Zeitpunkt der Registrierung der Betrachter meiner SingleLiveEvent ist der anonyme Beobachter Klasse in meinem SingleLiveEvent

debug of registration

  • zum Zeitpunkt der Entfernung der Beobachter von meinem SingleLiveEvent entfernt werden soll, ist ein MediatorLiveData (die tatsächlich die frühere anonyme Klasse in meinem SingleLiveEvent beobachtet)

debug of removal

Was nie von den Beobachtern des SingleLiveEvent (also wenn Ausrichtung ändert mehrmals mein SingleLiveEvent hat mehrere Beobachter) entfernt wird, ist, dass mein erster Beobachter geschieht.

Ich kann nicht herausfinden, warum dies nicht derselbe Beobachter zum Zeitpunkt der Entfernung ist. Wenn es ohne einen Transformationsschritt reproduziert wird, gibt es kein solches Problem.

Hat jemand einen Hinweis auf dieses Verhalten? Sind SingleLiveEvent (nicht Teil des Frameworks) und Transformationen nicht zusammen gedacht?

Antwort

0

Ich habe herausgefunden, dass dies aufgrund der Tatsache ist, dass Transformations eine MediatorLiveData verwenden, die die SingleLiveEvent als eine referenzierte Quelle verwendet. Diese Quelle wird für die Registrierung und Entfernung von sich selbst als Beobachter verwendet.

Die SingleLiveEvent führt jedoch einen Zwischenbeobachter zur Registrierungszeit ein. Die SingleLiveEvent verweist auf diesen Zwischenbeobachter und weiß nichts über die MediatorLiveData.

Zum Zeitpunkt der Entfernung versucht die MediatorLiveData, sich als Beobachter von der SingleLiveEvent abzumelden. Da die SingleLiveEvent darüber nicht weiß, hält es den Zwischenbeobachter.

Am Ende ist der Prozess nicht symmetrisch und im Laufe der Zeit (wie der Benutzer das Telefon dreht), hat die SingleLiveEvent mehr und mehr Beobachter.

Ich weiß nicht, ob ich etwas verpasst habe oder ob die MediatorLiveData nicht mit SingleLiveEvent verwendet werden soll, aber ich habe eine Lösung für mein spezifisches Problem gefunden.

I gegeben, um eine Bezugnahme auf den Zwischen Beobachter im SingleLiveEvent und ich habe ihre removeObserver() Verfahren außer Kraft gesetzt, die Zwischen Beobachter und nicht (nur) die MediatorLiveData zu entfernen. Ich bin nicht so überzeugt von dieser Lösung, weil ich die Interna der LiveData nicht kenne. Insbesondere würde diese Lösung nur funktionieren, wenn die SingleLiveEvent nur mit MediatorLiveData als Beobachter verwendet wird (d. H. Nicht, wenn die Aktivität die SingleLiveEvent beobachtet) und nur wenn es einen einzelnen Beobachter gibt (was im Fall einer SingleLiveEvent Sinn macht). Es könnte andere Einschränkungen geben. Hier

ist der Code Ich habe das Recht Beobachter zu entfernen (singleLiveEventIntermediateObserver ist die anonyme Observer in der observe() Methode instanziiert):

@Override 
public void removeObserver(@NonNull Observer<T> observer) { 
    super.removeObserver(observer); 
    if (this.singleLiveEventIntermediateObserver != null) { 
     super.removeObserver(this.singleLiveEventIntermediateObserver); 
    } 
} 
Verwandte Themen