Home > Net >  Why LiveData can receive the last available data automatically?
Why LiveData can receive the last available data automatically?

Time:01-31

I am reading LiveData source code, and for this method:

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) { .. }

And this is part of its doc:

When data changes while the owner is not active, it will not receive any updates. If it becomes active again, it will receive the last available data automatically.

I was trying to figure out why LiveData can achieve this lifecycle-awareness. I read source code of setValue but still couldn't get it. Can anybody help me with the on the general idea? I appreciate the helps!

CodePudding user response:

Suppose you are not using live data and you are showing list of data with pagination concept . You as user have scroll down to view more and more data and application is calling apis to get data as you scroll . Now you have rotated your device so as developer we know that your activity will be recreated and user will be at initial stage again as all things were destroyed .. Well you can achieve this using onSaveInstance but you will have to code and manage yourself ..

So user will have to scroll again to view all data but imagine if you have some mechanism where you get your last updated data whenever activity lifecycle changes so you can easily set data again and allow user to use your app like nothing happened .. and here livedata concept come into picture with lifecycle awareness

Hope this answer will clear your doubts

Edit :- To understand how they are managing lifecycle , you can visit this link

enter image description here

CodePudding user response:

Read the source code of LiveData.java (in lifecycle-livedata-core:2.2.0@aar) again, it seems clear to me now.

When adding an observer to LiveData via liveData.observe(lifecycleOwner, Observer { .. } ), the magic happens in the observe method.

In the observe method, it puts the lifecycleOwner and the Observer into a new object called LifecycleBoundObserver like this:

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
  // ... some other code
owner.getLifecycle().addObserver(wrapper);

Important to note and we can also tell it from the last statement: the LifecycleBoundObserver is an instance of LifecycleObserver, that means, it can be notified when the given lifecycleOwner gets state updated, the key lies in the onStateChanged method of LifecycleBoundObserver.

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

So:

  1. If the lifecycleOwner (the Activity or Fragment) gets DESTROYED, it will remove the observer (the callback observer, not the LifecycleObserver), hence the observer won't be notified for new data once it's DESTROYED.
  2. If it is not DESTROYED, it requires the lifecycleOwner in Active states (STARTED or RESUMED), this is restricted by the return value from the method shouldBeAlive(), and finally the new data gets delivered to observer callback in the method activeStateChanged.
        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);
            }
        }
  1. If the input param newActive is true, then finally it will reach the statement of dispatchingValue(this) - the last statement, and if it is false (i.e.: inactive states: PAUSED / STOPPED / DESTROYED), it won't call dispatchingValue(this), thus the observer callback won't be triggered.
  2. If the Activity / Fragment goes back to foreground from background, it becomes Active again, then the LifecycleBoundObserver will be notified and the onStateChanged will be called again, and this time, when calling activeStateChanged(newActive), it passes true, therefore, dispatchingValue(this) will be called, and the latest data set via setValue or post will be picked up, that's the reason for explaining why the Activity can get the last emitted / latest value of LiveData.
  • Related