Android LiveData原理分析

Posted 冬天的毛毛雨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android LiveData原理分析相关的知识,希望对你有一定的参考价值。

作者:PG_KING

前言

官方介绍:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
它有以下的优势:

  • 确保界面符合数据状态
  • 不会发生内存泄露
  • 不会因Activity停止而导致崩溃
  • 不再需要手动处理生命周期
  • 数据始终保持最新状态
  • 适当的配置修改
  • 共享资源

接下来我们通过基本使用,一步一步的探究LiveData是如何实现这些优势的。

使用

创建 LiveData 对象

public class CoursePreviewModel extends ViewModel 

    /**
     * view状态
     */
    private MutableLiveData<List<CoursePreviewBean.DataBean>> mStateLiveData;

    public MutableLiveData<List<CoursePreviewBean.DataBean>> viewStateLive() 
        if (mStateLiveData == null) 
            mStateLiveData = new MutableLiveData<>();
        
        return mStateLiveData;
    

观察 LiveData 对象

class CoursePreviewActivity : AppCompatActivity() 

    // Use the 'by viewModels()' Kotlin property delegate
    // from the activity-ktx artifact
    private val mViewModel: CoursePreviewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        // 监听
        mViewModel.viewStateLive().observe(this, target -> 
        );
    

原理分析

这里我们先提出几个问题:

  1. LiveData怎么绑定到应用组件的生命周期呢
  2. 为什么不需要我们手动处理生命周期,为什么不会因Activity停止而导致崩溃
  3. 数据变化又是怎么触发的呢

带着这些问题,我们逐步往里看

一、应用组件生命周期的绑定

当我们需要观察数据变化时,需要调用LiveData的observe接口,这也是LiveData与Activity或Fragment产生关联的地方:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) 
        assertMainThread("observe");
        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);
    

这个方法需要接收两个参数:

  • LifecycleOwner:生命周期所有者
  • Observer:观察者,用于观察获取变化后的数据

通常我们在Activity或Fragment中使用LiveData,看下androidx包提供的AppCompatActivity和Fragment都是实现了LifecycleOwner接口。所以直接将this作为第一个参数即可。

继续分析上边的observe方法

  • 这里会首先判断是否在主线程执行,假如不是即会抛出异常
assertMainThread("observe");
static void assertMainThread(String methodName) 
    if (!ArchTaskExecutor.getInstance().isMainThread()) 
        throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
                + " thread");
    

  • 假如是应用组件的生命周期已经是destory的状态,即不会继续往下执行
if (owner.getLifecycle().getCurrentState() == DESTROYED) 
    // ignore
    return;

  • 通过LifecycleBoundObserver进行真正的逻辑处理,这里我们继续往下走,待会再回头分析这块
  • 判断相同的observer不能被不同的LifecycleOwner处理
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;

这里主要用到SafeIterableMap这个结构保存owner和observer的关系:

// put之前先判断是否已经包含了该key,假如是则直接返回相应的value
public V putIfAbsent(@NonNull K key, @NonNull V v) 
    Entry<K, V> entry = get(key);
    if (entry != null) 
        return entry.mValue;
    
    put(key, v);
    return null;

  • 最后,将生命周期所有者与observer绑定起来,这样子observer即可接收到相应的生命周期
owner.getLifecycle().addObserver(wrapper);

可以看到,这里不是直接add传递进来的Observer,而是上边提到的包装了owner和Observer的LifecycleBoundObserver。所以接下来我们好好分析下它:

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() 
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    

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

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

    @Override
    void detachObserver() 
        mOwner.getLifecycle().removeObserver(this);
    

可以看到,LifecycleBoundObserver是实现了LifecycleEventObserver接口,而LifecycleEventObserver接口是继承于LifecycleObserver接口的,因此可以看出主要是在LifecycleBoundObserver这里完成生命周期的处理。

二、为什么不需要手动处理生命周期

经过上边的分析,我们发现其实主要的生命周期处理工作是在LifecycleBoundObserver里边完成的。我们继续看它的源码,有这么两个方法:

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

我们先看detachObserver,这里明显就是用于解除绑定的。我们找下哪里调用了这个方法:

@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) 
    assertMainThread("removeObserver");
    ObserverWrapper removed = mObservers.remove(observer);
    if (removed == null) 
        return;
    
    removed.detachObserver();
    removed.activeStateChanged(false);

主要是在LiveData的removeObserver,那继续找下该方法的调用。发现又回到了LifecycleBoundObserver本身,不错就是在onStateChanged里边,它会接收生命周期的变化通知,当发现mOwner.getLifecycle().getCurrentState() == DESTROYED即组件处于destory状态时,自动移除相应的观察者,这样子当activity或fragment销毁时,不会再收到相应的事件通知

三、数据变化怎么触发的

我们继续将核心放在LifecycleBoundObserver的onStateChanged方法上。当组件还没销毁,即会继续往下跑activeStateChanged(shouldBeActive());,该方法定义在ObserverWrapper类里边(LifecycleBoundObserver继承于它)

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);
    

当处于活跃状态,即mActive为true时,会走到dispatchingValue(this);。我们继续看

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<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) 
                considerNotify(iterator.next().getValue());
                if (mDispatchInvalidated) 
                    break;
                
            
        
     while (mDispatchInvalidated);
    mDispatchingValue = false;

核心在于considerNotify方法

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;
    observer.mObserver.onChanged((T) mData);

直接看到最后一句,这里直接调用了observer.mObserver.onChanged((T) mData);,这里就会触发数据变化回调。而这里的mObserver即是我们在刚开始传递进来的。

其他

一、observeForever

其实,LiveData除了提供observe用于方法,还提供了一个observeForever方法

@MainThread
public void observeForever(@NonNull Observer<? super T> observer) 
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) 
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    
    if (existing != null) 
        return;
    
    wrapper.activeStateChanged(true);

这里可以看到,没有跟生命周期绑定,也不再使用LifecycleBoundObserver进行包装,而是使用AlwaysActiveObserver:

private class AlwaysActiveObserver extends ObserverWrapper 

    AlwaysActiveObserver(Observer<? super T> observer) 
        super(observer);
    

    @Override
    boolean shouldBeActive() 
        return true;
    

AlwaysActiveObserver和LifecycleBoundObserver都继承于ObserverWrapper,但是前者没有重写它的detachObserver方法,因此它不会被自动移除监听。只能通过手动调用removeObserver进行移除。

二、postValue和setValue

两个方法都可以用于更新值,分析下区别:

protected void postValue(T value) 
    boolean postTask;
    synchronized (mDataLock) 
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    
    if (!postTask) 
        return;
    
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);


@MainThread
protected void setValue(T value) 
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);

  1. setValue必须在主线程调用,否则会抛出异常
  2. postValue用于在其他线程更新值,核心在:ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);,这会切回到主线程执行。
  3. 由于postValue是通过handler的消息派发进行处理,而setValue直接设值,因此这种情况需要注意:
// 源码提示
Posts a task to a main thread to set the given value. So if you have a following code executed in the main thread:
       liveData.postValue("a");
       liveData.setValue("b");
       
The value "b" would be set at first and later the main thread would override it with the value "a".

如果在主线程执行已发布任务之前多次调用此方法,则只会调度最后一个值。这个是怎么实现的呢?我们看下postValue里边的处理

protected void postValue(T value) 
    boolean postTask;
    synchronized (mDataLock) 
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    
    if (!postTask) 
        return;
    
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);


private final Runnable mPostValueRunnable = new Runnable() 
    @SuppressWarnings("unchecked")
    @Override
    public void run() 
        Object newValue;
        synchronized (mDataLock) 
            newValue = mPendingData;
            mPendingData = NOT_SET;
        
        setValue((T) newValue);
    
;

第一次,mPendingData的值为NOT_SET,因此postTask为true,而mPendingData为设置的value。直到mPostValueRunnable被执行时,mPendingData才被重新赋值为NOT_SET。假如在主线程执行前,不断的调用postValue,postTask一直为false,mPendingData会被更新到最新设置的值,但是mPostValueRunnable不会被重复执行。

以上是关于Android LiveData原理分析的主要内容,如果未能解决你的问题,请参考以下文章

Android LiveData实现原理

Android LiveData实现原理

Android LiveData实现原理

Android LiveData组件分析

Android LiveData组件分析

Android LiveData组件分析