Android LiveData实现原理

本文基于:

androidx.lifecycle:lifecycle-viewmodel:2.3.0

androidx.lifecycle:lifecycle-livedata-core:2.3.0

一.LiveData简介

LiveData是google随Jetpack发布的,是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。详细的文档介绍参考:

https://developer.android.com/topic/libraries/architecture/livedata


二.LiveData原理

1. 示例

这个例子基于之前ViewModel的例子(https://blog.csdn.net/Beatles_The/article/details/114793959),在ViewModel里,我们通过interface OnTimeChangeListene来处理数据的变化监听,是一种观察者模式,Activity中使用的时候需要先调用setOnTimeChangeListener把观察者传入,在ViewModel中保存一个观察者列表,在被观察的数据变化时,调用观察者的onTimeChanged方法。如果要观察的数据很多,则需要定义大量的接口,代码显得冗余。LiveData组件就是为了简化这个而来的,帮助我们完成ViewModel与页面组件之间的通信。所以,LiveData通常是被放在ViewModel中使用。

public class MyLiveDataViewModel extends ViewModel {
    private static final String TAG = "MyLiveDataViewModel";
    private Timer mTimer;
    private MutableLiveData<Integer> mCurrentSecond;

    public void startTiming() {
        if (mTimer == null) {
            mCurrentSecond.setValue(0);
            mTimer = new Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    mCurrentSecond.postValue(mCurrentSecond.getValue() + 1);
                }
            };
            mTimer.schedule(timerTask, 1000, 1000);
        }
    }

    public LiveData<Integer> getCurrentSecond() {
        if (mCurrentSecond == null) {
            mCurrentSecond = new MutableLiveData<>();
        }
        return mCurrentSecond;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        Log.d(TAG, "onCleared()");
        mTimer.cancel();
    }
}

public class ViewModelActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.viewmodel);
        final Button tvLiveTime = findViewById(R.id.btn_demo_livedata_viewmodel);
        ViewModelProvider vmp = new ViewModelProvider(this,
               ViewModelProvider.AndroidViewModelFactory.getInstance(
                    this.getApplication()));
        MyLiveDataViewModel liveDataViewModel = vmp.get(MyLiveDataViewModel.class);
        final MutableLiveData<Integer> liveData = (MutableLiveData<Integer>)
               liveDataViewModel.getCurrentSecond();
        liveData.observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(@Nullable Integer second) {
                runOnUiThread(() -> tvLiveTime.setText("LIVE-TIME:" + second));
            }
        });
        liveDataViewModel.startTiming();
    }
}

运行后,和之前ViewModel的demo效果是一样的,这里去掉了回调的Listener接口,由LiveData来实现。

2. 注册Observer

我们先看一下,LiveData的类图:

LiveData的结构其实很简单,也是一个观察者模式,LiveData内部保存一个mObservers的列表,和Lifecycle类似,observer()方法传入的Observer对象会被包装成LifecycleBoundObserver,observerForever()方法传入的Observer对象会被包装成AlwaysActiveObserver。二者的区别是LifecycleBoundObserver实现了LifecycleObserver,当LifecycleOwner生命周期结束时,会被自动的从mObservers中remove掉:

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

所以observer()的第一个参数需要传入LifecycleOwner对象。

3. 数据变化分发

当数据变化时,调用LiveData的setValue和postValue进行更新,在主线程的时候调用setValue,否则调用postValue,其内部最终也是调用setValue,setValue的流程如下:

其中,dispatchValue可以指定Observer,这时候只通知这个Observer,如果没有指定,则循环所有的Observer。dispatchValue考虑了多线程同时调用的情况:

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

第一个线程setValue后,会设置mDispatchingValue,然后尝试通知列表每一个观察者,比如通知到一半,这个时候,第二个线程setValue后,请求dispatchValue的时候,通过mDispatchingValue的值发现正在更新,它会mDispatchInvalidated设置并直接退出,第一个线程通知过程发现mDispatchInvalidated被设置,直接break,从当前的列表中循环中退出,在外层循环中发现mDispatchInvalidated被设置,从头开始通知列表。如下示意图:

列表中5个Observer,Thread1调用setValue(2),将LiveData的值设置为2,接下来通知列表,通知到第三个的时候,Thread2调用setValue(3),将LiveData的值设置为3,这个时候Thread2将退出,然后Thread1重头开始通知列表。

这里的解释都是基于多线程,按理说mDispatchingValue和mDispatchInvalidated需要设置volatile,但是源码中并没有,mData是volatile的:

private volatile Object mData;
private boolean mDispatchingValue;
private boolean mDispatchInvalidated;

个人觉得mDispatchingValue和mDispatchInvalidated需要设置volatile,但是不设置,可能问题也不大,因为mData是volatile的,上面的例子中,如果第二个线程setValue(3),在dispatchingValue的时候,判断mDispatchingValue是false(因为没有同步导致的),那么Thread2也会执行一遍通知,但是通知的数据是对的,同样Thread1由于mDispatchInvalidated判断不对的原因,不会提前结束旧的通知,但是其mData已经是新的。也就是说,不设置volatile,可能导致通知变多,但数据并没有通知错。而且即使设置了,有的Observer也会通知多次,例如上面的例子,前3个Observer会通知2次。

4. 数据Active

前面的类图可以看到LiveData有两个自身生命周期有关的方法onActive和onInactive,LiveData的Active的定义是至少有一个Observer是Active的。ObserverWrapper里有一个activeStateChanged方法,这个是处理Observer的Active状态的,先来看其实现:

void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
       return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive owner
    mActive = newActive;
    changeActiveCounter(mActive ? 1 : -1);
    if (mActive) {
       dispatchingValue(this);
    }
}

mActive是ObserverWrapper当前的活跃状态,接下来调用的changeActiveCounter是LiveData的方法,不是ObserverWrapper的,实现如下:

void changeActiveCounter(int change) {
    int previousActiveCount = mActiveCount;
    mActiveCount += change;
    if (mChangingActiveState) {
        return;
    }
    mChangingActiveState = true;
    try {
        while (previousActiveCount != mActiveCount) {
            boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
            boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
            previousActiveCount = mActiveCount;
            if (needToCallActive) {
                onActive();
            } else if (needToCallInactive) {
                onInactive();
            }
         }
    } finally {
       mChangingActiveState = false;
    }
}

只是一个简单的计数,如果发现旧的ActiveCount是0,新的大于0,说明有Observer是活跃的,那么LiveData也是活跃的,调用onActive,反过来,旧的ActiveCount大于0,新的是0,说明没有Observer是活跃的,那么LiveData也是不活跃的,调用onInactive。

activeStateChanged最后一个处理逻辑,如果该Observer是被激活的,则调用dispatchingValue(this)去通知状态,前面知道dispatchingValue参数是一个Observer的话,会调用该Observer的onStateChange的回调。

接下来看看什么情况下会调用上面的activeStateChanged:

(1)observeForever,由于这个Observer不依赖生命周期,一旦被注册,直接调用activeStateChanged(true),表示激活。

(2)removeObserver,移除Observer,调用activeStateChanged(false),表示非激活状态。

(3)onStateChanged,这个是LifeCycle的生命周期回调,也就是说ObserverWrapper生命周期变化时,会调用activeStateChanged(shouldBeActive()),shouldBeActive判断生命周期是不是Active的:

boolean shouldBeActive() {
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

(4)considerNotify,前面已经分析,这个是通知状态变化时的方法,其内部调用Observer的onStateChange,在调用前,会判断这个Observer是否还是存活的,这个是为了预防在处理通知的过程中,某些Observer已经不是存活的(比如执行removeObserver但是还没有收到事件):

if (!observer.shouldBeActive()) {
  observer.activeStateChanged(false);
  return;
}

三.总结

结合LiveData和ViewModel,可以很方便的监听数据的变化,其本质也是一个观察者模式,不需要定义各种interface来回调数据变化的方法,都放到onStateChange中来回调。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值