The use and detailed explanation of LiveData

1. LiveData is easy to use

The code implementation part of this article mainly uses Java to explain.
LiveData is mainly convenient for data observation, UI update or business processing.
The simple code implementation of LiveData is as follows

// 创建一个MutableLiveData对象,这个使用LiveData的子类MutableLiveData
// MutableLiveData暴露了postValue和setValue方法用于通知数据变化
MutableLiveData<Object> liveData = new MutableLiveData<>();


// 在UI线程中调用该方法通知数据变更
liveData.setValue(object);

// 在子线程中调用该方法通知数据变更,该方法中切换到UI线程后调用setValue方法
liveData.postValue(object);


// 监听数据变化,进行界面更新等操作,该方法一般放在Activity onCreate方法中调用,只注册一次
liveData.observe(this, new Observer<Object>() {
    
    
    @Override
    public void onChanged(Object o) {
    
    
     // TODO 此处进行o对象的数据与界面进行绑定刷新
    }
});

2. Principle of LiveData

The core of LiveData is actually the observer method, which is used to register observers to monitor data changes; and the setValue method is used to notify data changes; why LiveData is more useful, because it can monitor the interface life cycle to refresh data, and does not Users need to switch threads by themselves.

1) Observe method analysis

The following is the source code of the observe method:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    
    
    // 判断是否在主线程中调用该方法,如果不是在主线程中调用抛出IllegalStateException异常
    assertMainThread("observe");
    // 判断LiveData观察者的生命周期(一般为Activity和fragment)是否为DESTROYED
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
    
    
        // ignore
        return;
    }
    // 创建LifecycleBoundObserver对象,用于监听LiveData观察者的生命周期变化
    // LifecycleBoundObserver 为 ObserverWrapper 子类
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    // 将wrapper保存到LiveData对象的mObservers map中,若mObservers中已存在相同key的observer
    // 直接将observer对应的ObserverWrapper对象返回
    // (LiveData的mObservers中还可能保存ObserverWrapper的子类AlwaysActiveObserver的对象)
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    // 若同一个observer第一次调用observe方法,existing 为null值
    // 若同一个observer重复调用observe方法,!!xisting.isAttachedTo(owner)为false也不会执行如下判断
    // 若同一个observer,先调用observeForever再调用observe方法执行如下判断代码
    if (existing != null && !existing.isAttachedTo(owner)) {
    
    
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
    
    
        return;
    }
    // 将本次的观察者封装成声明感知组件后添加到该LiveData的持有者的生命周期通知观察队列中
    owner.getLifecycle().addObserver(wrapper);
}

So far, add the data change observer to the observer map table of the LiveData object, and perform corresponding business operations when the observer monitors the LiveData data change.

2) setValue method parsing

Because the postValue method is mainly to switch to the UI thread, and then call the setValue method, so I will not introduce the postValue method here, but mainly talk about the setValue method.

@MainThread
protected void setValue(T value) {
    
    
    assertMainThread("setValue");
    // 版本号,该值用于判断是否通知观察者数据发生变成,在后面considerNotify方法中有使用,每次调用该方法自增1
    mVersion++;
    mData = value;
    // setValue方法调用了该方法,直接往下面看一下该方法的代码
    dispatchingValue(null);
}


/**
 * 这个方法里面看着代码虽多,但是这里主要看关键代码
 */
@SuppressWarnings("WeakerAccess")
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    
    
    // 若正在进行数据变更通知,本次调用直接返回true
    if (mDispatchingValue) {
    
    
        // 若代码走到这里且数据通知未结束,会让第一次setValue方法调用时的该方法内while循环重新走一遍
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
    
    
        mDispatchInvalidated = false;
        if (initiator != null) {
    
    
            // 新添加的观察者,产生粘性事件,会执行这里,具体可以看调用该方法时initiator不为空的代码
            considerNotify(initiator);
            initiator = null;
        } else {
    
    
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    
    
                // 调用setValue方法,会遍历LiveData的mObservers,逐一通知观察者数据发生变更
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) {
    
    
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}


@SuppressWarnings("unchecked")
private void considerNotify(ObserverWrapper observer) {
    
    
    // 先判断观察者是否处于活跃状态
    if (!observer.mActive) {
    
    
        return;
    }
    
    // 判断观察者的持有者的生命周期是否处于STARTED、RESUMED状态
    if (!observer.shouldBeActive()) {
    
    
        // 更改观察者的状态为非mActive状态,调用该方法会重新调用dispatchingValue方法且值不为空(重新对该观察者分发数据变更通知)
        observer.activeStateChanged(false);
        return;
    }
    // 判断mLastVersion的值是否大于等于当前数据变更的版本
    // 新添加一个观察者的时候,该值初始化为-1,预防LiveData粘性事件的办法就是通过反射改掉mLastVersion的值
    if (observer.mLastVersion >= mVersion) {
    
    
        return;
    }
    observer.mLastVersion = mVersion;
    // 这里,通知观察者数据已经发生变更
    observer.mObserver.onChanged((T) mData);
}

The above content is all the content of LiveData's use demo and source code analysis.

Guess you like

Origin blog.csdn.net/qq_36224961/article/details/126227295