LiveData usage and source code of Jetpack family bucket

Introduction

LiveData Is an observable data store class. Unlike regular observable classes, LiveData is lifecycle aware, meaning it follows the lifecycle of other application components such as Activity, Fragment, or Service. This awareness ensures that LiveData only updates application component observers that are in an active lifecycle state.

Observer LiveData considers an observer to be active if its lifetime  (represented by the  class) is in the STARTED OR  RESUMED state. LiveData will only notify active observers of updates. Inactive observers registered to observe  LiveData objects will not be notified of changes.

You can register  LifecycleOwner observers paired with objects that implement the interface. With this relationship,   this observer can be removed when Lifecycle the state of the corresponding object changes  . DESTROYEDThis is especially useful for Activities and Fragments because they can safely observe  LiveData objects without worrying about leaks (the system unsubscribes from Activities and Fragments immediately when their lifecycle is destroyed).

Advantages of LiveData

  • Make sure the interface conforms to the data state

LiveData follows the observer pattern. Observer LiveData notifies objects when the underlying data changes  . You can integrate code to  Observer update the interface in these objects. This way, you don't need to update the UI every time your app's data changes, because the watcher does it for you.

  • no memory leak

Observers are bound to  Lifecycle objects and clean up after their associated lifetime is destroyed.

  • No crash due to activity stop

If the observer's lifecycle is inactive (such as an Activity back on the stack), it will not receive any LiveData events.

  • No more manual handling of lifecycles

The UI component just observes the relevant data and does not stop or resume the observation. LiveData will automatically manage all of these operations as it is aware of the relevant lifecycle state changes as it observes.

  • Data is always up to date

If the lifecycle becomes inactive, it will receive the latest data when it becomes active again. For example, an activity that was once in the background receives the latest data as soon as it returns to the foreground.

  • Appropriate configuration changes

If an Activity or Fragment is recreated due to a configuration change (such as a device rotation), it receives the latest available data immediately.

  • Share resource

You can use the singleton pattern to extend  LiveData objects to encapsulate system services so that they can be shared across applications. LiveData An object connects to a system service once, and then any observers that need the corresponding resource simply observe the  LiveData object. See Extending LiveData for details .

dependency import

If your project introduces the androidx.appcompat:appcompat:***package, the default LiveData has been introduced

Kotlin

    dependencies {
        val lifecycle_version = "2.4.0-alpha02"

        // LiveData
        implementation("androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version")  
    }

Java

    dependencies {
        val lifecycle_version = "2.4.0-alpha02"

        // LiveData
        implementation("androidx.lifecycle:lifecycle-livedata:$lifecycle_version")
    }

basic use

class MyViewModel : ViewModel() {

    val name = MutableLiveData<String>()

    private fun getName() {
       name.value="数据内容"
    }
}

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {

        val viewModel = ViewModelProvider(this)[MyViewModel::class.java]

        viewModel.getName().observe(this, Observer<String>{ name ->
            // update UI
        })
    }
}

Principle analysis

We know that the use of livedata is very simple, it is implemented using the observer pattern

  1. add observer
  2. Set the value when the data changes, which will call back the Observer's onChanged method
public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}

observe method

LiveData contains two methods for adding data observers (Observer), namely

  • observe(LifecycleOwner , Observer) 生命周期安全的
  • observeForever(Observer)

The difference between the two methods to the outside is only whether the guarantee of life cycle safety is provided.

Lifecycle safety observe

@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //限定只能在主线程调用 observe 方法
        assertMainThread("observe");
        //当 Lifecycle 已经处于 DESTROYED 状态时,此时进行 observe 是没有意义的,直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //根据传入参数构建一个新的代理 Observer
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //将 observer 作为 key,wrapper 作为 value 进行存储
        //当 mObservers 不包含该 key 时,调用 putIfAbsent 会返回 null
        //当 mObservers 已包含该 key 时,调用 putIfAbsent 不会存储 key-value,并会返回之前保存的 value
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            //走到此步,说明之前 LiveData 内部已经持有了 observer 对象,
            //且该 observer 对象已经绑定了其它的 LifecycleOwner 对象
            //此时直接抛出异常
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            //observer 之前已经传进来过了,此处直接返回
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

The incoming LifecycleOwnerparameters mean that the Lifecycle object is carried, and LiveData will notify the data at the appropriate time according to the callback changes of Lifecycle's life cycle events, and automatically remove the Observer when the Lifecycle object is in the DESTROYED state, which is also LiveData to avoid memory leaks the most important point.

The above code is used LifecycleBoundObserver, it is the implementation class of the abstract class ObserverWrapper. ObserverWrapper is used to wrap the Observer object passed in from the outside, define specific abstract methods and common logic for subclasses, and mainly provide a common state distribution function.

class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        //只有当 Lifecycle 的当前状态是 STARTED 或者 RESUMED 时
        //才认为 Lifecycle 是处于活跃状态
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    //LifecycleEventObserver 的实现方法
    //当 Lifecycle 的生命周期状态发生变化时就会调用此方法
    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
                               @NonNull Lifecycle.Event event) {
        //如果 Lifecycle 已经处于 DESTROYED 状态了,则主动移除 mObserver
        //这就是 LiveData 可以避免内存泄露最重要的一个点
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        activeStateChanged(shouldBeActive());
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        //移除 mObserver
        mOwner.getLifecycle().removeObserver(this);
    }
}

The entire event flow of LifecycleBoundObserver is as follows:

  1. The life cycle of the Lifecycle changes, so the onStateChanged function is called back
  2. The onStateChanged function first determines whether the Lifecycle is already in the DESTROYED state. If so, it directly removes the Observer, and the entire callback process ends, otherwise, continue with the following process
  3. onStateChanged calls the activeStateChanged() function, and the activeStateChanged() function determines whether the active state of the Lifecycle has changed. If it switches from the inactive state to the active state, if so, it calls the dispatchingValue() function to distribute the value, and finally according to the internal observerWrapper. The value version number mLastVersion is used to judge whether there is a new value that needs to be called back.
private abstract class ObserverWrapper {

    //外部传进来的对 LiveData 进行数据监听的 Observer
    final Observer<? super T> mObserver;

    //用于标记 mObserver 是否处于活跃状态
    boolean mActive;

    //用于标记 Observer 内最后一个被回调的 value 的新旧程度
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    //用于获取当前 Lifecycle 是否处于活跃状态
    abstract boolean shouldBeActive();

    //用于判断 mObserver 是否和 LifecycleOwner(即 Lifecycle)有绑定关系
    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    //移除 mObserver
    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        //判断当前 LiveData 所有的 Observer 是否都处于非活跃状态
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        //更新 LiveData 当前所有处于活跃状态的 Observer 的数量
        LiveData.this.mActiveCount += mActive ? 1 : -1;
        if (wasInactive && mActive) {
            //如果 LiveData 处于活跃状态的 Observer 数量从 0 变成了 1,
            //则回调 onActive 方法
            onActive();
        }
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            //如果 LiveData 处于活跃状态的 Observer 数量从 1 变成了 0,
            //则回调 onInactive 方法
            onInactive();
        }
        if (mActive) {
            //如果 mObserver 变成了活跃状态,则向其回调新值
            dispatchingValue(this);
        }
    }
}

ObserverWrapper has two subclasses:

The difference between LifecycleBoundObserver and AlwaysActiveObserver is whether it is bound to the life cycle .

non-lifecycle safe observeForever

@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    //限定只能在主线程调用 observe 方法
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        //会走到这一步,是因为之前已经先用该 observer 对象调用了 observe(LifecycleOwner,Observer)
        //这里直接抛出异常
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        //如果之前已经添加过 observer 对象了的话,则直接返回
        return;
    }
    //主动触发 activeStateChanged 函数,因为当前 LiveData 可能已经被设置值了
    wrapper.activeStateChanged(true);
}

The above code uses AlwaysActiveObserver, which is also an implementation class of the abstract class ObserverWrapper. The return value of shouldBeActive() is fixed to true, which means that a callback will be made whenever there is a data change. So the use of the observeForever() function must be done later 主动移除Observerto avoid memory leaks and NPE.

Update the value of LiveData

There are two ways to update the value of LiveData, namely:

  • setValue(T value)
  • postValue(T value)

setValue

The setValue(T) function is limited to being called by the main thread only.

/**
 * Sets the value. If there are active observers, the value will be dispatched to them.
 * <p>
 * This method must be called from the main thread. If you need set a value from a background
 * thread, you can use {@link #postValue(Object)}
 *
 * @param value The new value
 */
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");

    //更新当前 value 的版本号,即 value 的新旧程度
    mVersion++;

    mData = value;
    dispatchingValue(null);
}

dispatchingValue()The function is designed ingeniously, using two global Boolean variables mDispatchingValue and mDispatchInvalidated to realize the logic of judging old and new values, discarding old values, and re-publishing new values ​​globally.

//initiator 为 null 则说明需要遍历回调整个 mObservers
//initiator 不为 null 则说明仅回调 initiator 本身
void dispatchingValue(@Nullable ObserverWrapper initiator) {
   //如果当前正处于向 mObservers 发布 mData 的过程中(即 mDispatchingValue 为 true)
   //则将 mDispatchInvalidated 置为 true,用于标明有新值到来,正在回调的值是已经过时的了
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}
// 判断是否要将数据分发到指定的 ObserverWrapper
private void considerNotify(ObserverWrapper observer) {
    //如果 observer 处于非活跃状态,则直接返回
    if (!observer.mActive) {
        return;
    }
    //此处判断主要是为了照顾 LifecycleBoundObserver
    //由于 Lifecycle 有可能状态值 State 已经切换到了非活跃状态,但 LifecycleBoundObserver 还未收到事件通知
    //所以为了避免意外情况,此处主动检查 observer 的活跃状态并判断是否需要更新其活跃状态
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    //根据 observer 本部的 value 版本号 mLastVersion 来决定是否需要向其进行回调
    //为了避免重复向某个 observer 回调值,所以此处需要判断下
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

postValue

/**
 * Posts a task to a main thread to set the given value. So if you have a following code
 * executed in the main thread:
 * <pre class="prettyprint">
 * liveData.postValue("a");
 * liveData.setValue("b");
 * </pre>
 * The value "b" would be set at first and later the main thread would override it with
 * the value "a".
 * <p>
 * If you called this method multiple times before a main thread executed a posted task, only
 * the last value would be dispatched.
 *
 * @param value The new value
 */
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

The postValue(T) function does not limit the thread of the caller. It can be called by both the main thread and the sub-thread, so there is the possibility of multi-thread competition. The point of the postValue(T) function is to understand that it switches from sub-threads to state changes between the main thread.

Before mPostValueRunnable is executed, all values ​​passed by the postValue(T) function will be saved to the variable mPendingData, and only 保留最后一个, mPendingData will not be reset until mPostValueRunnable is executed, so use the postValue(T) function in multi-threaded In the case of simultaneous calls or single-threaded continuous calls, there is a possibility of losing values ​​(the external Observer can only receive the latest value).

Guess you like

Origin blog.csdn.net/ajsliu1233/article/details/120732063