Android LiveData Quellcode Analyse-Quellcode 100 Tage lesen (2)

0. Einleitung

LiveData gehört laut Dokumentbeschreibung auch zur JetPack-Build-Sammlung. LiveData ist eine beobachtbare Datenhalterklasse. Im Gegensatz zu normalen Observablen ist LiveData lebenszyklusabhängig. Dies bedeutet, dass der Lebenszyklus anderer Anwendungskomponenten wie Aktivität, Fragment oder Dienst berücksichtigt wird. Diese Kenntnis stellt sicher, dass LiveData nur Beobachter von Anwendungskomponenten aktualisiert, die sich im aktiven Lebenszyklus befinden.
Vorteile (Folgendes wird aus dem Google-Dokument entnommen und von Google übersetzt)
(1) Stellen Sie sicher, dass Ihre Benutzeroberfläche Ihrem Datenstatus entspricht.
LiveData folgt dem Beobachtermuster. Wenn sich der Lebenszyklusstatus ändert, benachrichtigt LiveData das Observer-Objekt. Sie können Code zusammenführen, um die Benutzeroberfläche in diesen Observer-Objekten zu aktualisieren. Jedes Mal, wenn sich die Anwendungsdaten ändern, können Ihre Beobachter die Benutzeroberfläche bei jeder Änderung aktualisieren, anstatt die Benutzeroberfläche zu aktualisieren.
(2) Es liegt kein Speicherverlust vor. Der
Beobachter ist an das Lifecycle-Objekt gebunden und bereinigt, nachdem der zugehörige Lebenszyklus zerstört wurde.
Kein Absturz aufgrund von Inaktivität
Wenn der Lebenszyklus des Beobachters inaktiv ist (z. B. bei Aktivitäten im Back-End-Stack), werden keine LiveData-Ereignisse empfangen.
(3) Eine manuelle Lebenszyklusverarbeitung von
UI-Komponenten ist nicht mehr erforderlich, da nur verwandte Daten beobachtet werden, und wird die Beobachtung nicht stoppen oder fortsetzen. LiveData verwaltet all dies automatisch, da es während der Beobachtung die relevanten Änderungen des Lebenszyklusstatus kennt.
(4) Immer die neuesten Daten aufbewahren
Wenn der Lebenszyklus inaktiv wird, werden die neuesten Daten empfangen, wenn er wieder aktiv wird. Beispielsweise erhalten Hintergrundaktivitäten die neuesten Daten unmittelbar nach der Rückkehr in den Vordergrund.
(5) Geeignete Konfigurationsänderungen
Wenn Aktivitäten oder Segmente aufgrund von Konfigurationsänderungen (z. B. Gerätedrehung) neu erstellt werden, werden die neuesten verfügbaren Daten sofort empfangen.
(6) Ressourcen teilen
Sie können das Singleton-Muster verwenden, um LiveData-Objekte so zu erweitern, dass Systemdienste umbrochen werden, damit sie in der Anwendung gemeinsam genutzt werden können. Das LiveData-Objekt ist einmal mit dem Systemdienst verbunden, und dann kann jeder Beobachter, der die Ressource benötigt, nur das LiveData-Objekt überwachen.

1. Verwenden Sie

class MainActivity : AppCompatActivity() {

    val curName: MutableLiveData<String> by lazy {

        MutableLiveData<String>()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        curName.observe(this, Observer<String> {
            println("value is $it")
        })
        curName.value="old value"
    }

}

Die Verwendung ist sehr einfach. Wenn sich der Wert des MutableLiveData-Objekts ändert, wird die onChanged-Methode des Beobachters gestartet, bei der MutableLiveData von LiveData erbt.

2. Zweck

(1) Wie führt LiveData die Lebenszykluserkennung durch?
(2) Wie werden Ereignisse aktualisiert ?
(3) Wie werden Speicherlecks vermieden?

3. Analyse

3.1 Wie führt LiveData die Lebenszykluserkennung durch?

Schauen Sie sich zunächst die Beobachtermethode von LiveData an

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

Sehen Sie in der letzten Zeile, owner.getLifecycle () addObserver (Wrapper). Eigentümer ist die Aktivität oder Fragment wir verwenden, das entspricht den früheren Artikel Lifecycle auf dem
Android - Lifecycle Quellcode-Analyse-Source - Code - Lese 100 Tage (1) , hier hinzufügen Der Listener ist LifecycleBoundObservr. Diese Klasse implementiert LifecycleObserver, mit dem der Lebenszyklus erfasst wird.

3.2 Aktualisieren von Ereignissen

Um ehrlich zu sein, ist dieses Steuerelement ein Beobachtermodus. Der Beobachter des Ereignisses ist der LifecycleBoundObserver. Sehen Sie sich die onStateChanged-Methode dieses Objekts an

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

Schauen Sie sich die activieStageChanged-Methode an

void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }

Diese Methode wird verwendet, um den Lebenszyklus zu behandeln und Speicherverluste zu vermeiden. Die tatsächliche Methode zur Beobachtung der Daten für die Verarbeitung ist die Methode dispatchingValue. Sehen Sie sich diese Methode an.

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

Wenn der ObserverWrapper-Parameter nicht null ist, rufen Sie die ConsiderNotify-Methode auf. Andernfalls iterieren Sie über mObservers und rufen Sie ConsiderNotify auf. Schauen Sie sich dann diese Methode an

private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
        //
        // we still first check observer.active to keep it as the entrance for events. So even if
        // the observer moved to an active state, if we've not received that event, we better not
        // notify for a more predictable notification order.
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }

Stellen Sie zunächst fest, ob ObserverWrapper aktiviert werden muss. Wenn es aktiviert werden muss, rufen Sie die activeStateChanged-Methode auf. Andernfalls rufen Sie die onChanged ((T) mData) -Methode unseres benutzerdefinierten Observer auf.

3.3 So vermeiden Sie Speicherlecks

Kehren Sie zu activeStateChanged (shouldBeActive ()) zurück, das in der onStateChanged-Methode aufgerufen wurde, und sehen Sie sich die shouldBeActive-Methode an

 @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        
 public boolean isAtLeast(@NonNull State state) {
            return compareTo(state) >= 0;
        }        

Diese Methode dient zum Vergleichen des aktuellen Status mit STARTED. Wenn STARTED oder RESUMED lautet, ist der in activeStateChanged übergebene Parameter true, andernfalls false. Schauen Sie dann auf die activeStateChanged-Methode zurück

void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

Wenn sich der Status nicht geändert hat, kehren Sie direkt zurück. Andernfalls beurteilen Sie, ob es sich um den aktiven Status gemäß newActive handelt.

          if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }

Rufen Sie dann die Methoden onActive und onInactive gemäß mActive und activeCount auf. Dies ist auf einen Blick klar, wenn der Lebenszyklus onStart aufruft, sich dieser im aktiven Zustand befindet und wenn sich onstop im inaktiven Zustand befindet, sodass er bei Änderungen der Daten nicht zur Observer-Methode wechselt, wodurch Speicherlecks vermieden werden .

Folgen Sie meinem öffentlichen Konto

Ich denke du magst

Origin blog.csdn.net/skateboard1/article/details/84330447
Empfohlen
Rangfolge