上一篇文章解析了一下Lifecycle
的源码剖析Lifecycle源码,因为Lifecycle
的应用很广泛,而JetPack的一些其他组件也涉及到了Lifecycle
,LiveData
也不例外,所以就在第一个写了Lifecycle
的文章,今天就来通过解析LiveData
的源码来了解其原理。
LiveData简介及基本使用
LiveData
是谷歌开发的jetpack的一个组件,通过LiveData
可以实现数据感知组件的生命周期,并且能在数据改变时通知那些监听了该该数据并且可见的组件。先来看看LiveData
的基本用法:
LiveDala
一般是配合ViewModel
使用的,ViewModel
不懂也没关系,并不影响阅读代码:
public class MyViewModel extends ViewModel {
private MutableLiveData ldBeanLiveData;
public MutableLiveData getLdBeanLiveData(){
if(ldBeanLiveData==null)
ldBeanLiveData = new MutableLiveData<>();
return ldBeanLiveData;
}
}
MutableLiveData
是LiveData
的子类,它的作用主要是向外界暴露setValue
和postValue
方法,可以在其他地方调用这两个方法来修改数据:
public class MutableLiveData extends LiveData {
public MutableLiveData(T value) {
super(value);
}
public MutableLiveData() {
super();
}
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
泛型用来接收数据类型,这里是LDBean
类型,LDBean
是一个实体类,只定义了一个属性id
:
public class LDBean {
private String id;
public LDBean(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
而在activity
中又是如何才能监听LiveData
数据变化的呢?
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
viewModel.getLdBeanLiveData().observe(this, new Observer() {
@Override
public void onChanged(LDBean ldBean) {
System.out.println(ldBean.getId());
}
});
}
viewModel
是MyViewModel
的一个实例,viewModel.getLdBeanLiveData()
就是viewModel
的成员变量ldBeanLiveData
,所以知不知道ViewModel
都不影响阅读LiveData
的代码。一旦ldBeanLiveData
调用setValue
或者postValue
,只要activity
是可见的(生命周期在onStart()
之后onStop()
之前),都会回调到这个匿名内部类Observer
的onChanged
方法:
viewModel.getLdBeanLiveData().setValue(new LDBean("1"));
viewModel.getLdBeanLiveData().postValue(new LDBean("2"));
不过setValue
是在主线程调用的,而postValue
是在子线程调用的。
这应该就已经知道了,实际上监听LiveData
数据变化的并不是activity
,而是这里的匿名内部类Observer
,而LiveData
又是如何做到感知activity
的生命周期的呢?又是如何做到将数据变化通知给Observer
的呢?接下来就进入源码仔细研究吧。
LiveData源码
先从LiveData
的observe
方法开始:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
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
类型,这里的owner
就是activity
,observer
就是之前的那个匿名内部类,这是一个接口,只有一个onChanged
方法:
public interface Observer {
void onChanged(T t);
}
LiveData
的observe
方法中首先会判断如果'owner'的生命周期为销毁状态,就直接return
,否则会将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;
}
}
这个类继承了ObserverWrapper
实现了LifecycleEventObserver
接口,看到这个就会想到Lifecycle
,ObserverWithState
中的成员变量mLifecycleObserver
就是这个接口的实例,activity
生命周期变化时就会调用到接口的onStateChanged
方法,而这里应该也是这样,现在记住就行,后面还会再分析。成员变量mOwner
就是activity
,再看一下ObserverWrapper
的构造方法:
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer super T> observer) {
mObserver = observer;
}
}
成员变量mObserver
就是构造函数传入的,mActive
标志了activity
是否可见,具体如何赋值后面会说。mLastVersion
表示了版本号, 先交代一下,后面再分析。
再回到LiveData
的observe
方法,新建了LifecycleBoundObserver
对象wrapper
以后,再将wrapper
添加到mObservers
中,mObservers
是SafeIterableMap
类型的对象,这是一个map结构,每一个元素有前驱结点和后继结点,这里就是一个观察者模式,wrapper
作为观察者观察LiveData
的数据变化,紧接着再做一些容错处理,最后再将wrapper
加入到owner
的lifecycle
的观察者列表中,因为wrapper
也是LifecycleEventObserver
的实例,所以wrapper
能够监听activity
的生命周期变化。
到这里可以总结一下,调用了LiveData
的observe
方法后,首先会将传入的activity
和observer
封装成一个LifecycleBoundObserver
对象,再让这个对象同时作为观察者观察LiveData
的数据变化和activity
生命周期的变化,也就是一个观察者同时观察两个被观察者。
下面就分析两个被观察者发生变化时是如何通知被观察者以及被观察者接收到通知以后又是如何工作的:
组件生命周期变化时观察者是如何工作的
从上一篇剖析Lifecycle源码中知道,当activity
生命周期发生变化时,最终会调用LifecycleBoundObserver
的onStateChanged
方法:
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
当被观察者activity
生命周期为destroyed
的时候,会执行removeObserver
方法,注意这个removeObserver
方法是LiveData
的方法:
@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
的观察者列表中删除,再调用观察者也就是LifecycleBoundObserver
的detachObserver
方法:
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
就是将观察者从Lifecycle
被观察者列表中删除,接着又会调用观察者的activeStateChanged
方法,先交代一下,这个方法会在被观察的activity
生命周期变化时被调用:
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
表示这个观察者是不是活动状态,当被观察的activity
可见时(再强调一下:生命周期在onStart()
之后onStop()
之前的activiy是可见的),则该观察者是活动的,mActive
的值为true
,被观察的activity
不可见则表示观察者是不活动的,mActive
的值为false
,第一个if
表示,如果activity
的可见性发生变化也就是观察者活动状态发生改变时才会往下走,否则直接结束该方法,activity
的可见性发生变化时,首先更新观察者活动状态,mActive
的值为newActive
,紧接着如果观察者的活动状态是由不活动转化为活动时,则先将LiveData
的处于活动状态的观察者个数加1,如果该观察者是唯一一个处于活动状态的观察者,则调用LiveData
的onActive
方法;如果观察者的活动状态是由活动转化为不活动时,则先将LiveData
的处于活动状态的观察者个数减1,如果该观察者是最后一个从活动状态转化为不活动状态的观察者时,也就是说LiveData
中不存在活动状态的观察者时,则调用LiveData
的onInactive
方法;这两个方法都是空方法,可以由开发人员自己继承去做一些操作。最后,如果是由不活动状态转化为活动状态,则会调用dispatchingValue
方法:
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, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
这个方法是LiveData
用来向观察者分发数据的方法。这里有两个boolean
类型的标志变量,mDispatchingValue
和mDispatchInvalidated
,mDispatchingValue
的值表示当前LiveData
是否正在分发数据,mDispatchInvalidated
可以设为true
来表示当前正在执行的分发操作无效,如果当前正在执行分发操作,则将当前正在执行的分发操作置为无效,然后直接退出该方法,否则就进行分发操作,将mDispatchingValue
设为 true
表示当前正在执行分发,然后就执行do while
循环,在循环里面执行分发操作,每次循环以后都会判断当前分发如果无效再执行一次循环分发数据,直到成功为止,首先会将分发操作置为有效,然后会判断该方法的参数是否为null
,不为null
则只向传入的观察者分发数据,否则就会循环遍历向所有的观察者分发数据,每次循环还会判断此次分发是否有效,因为也许分发过程中数据又发生了改变,那么就会退出遍历循环重新分发,分发给每个过程中调用的是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);
}
首先分发操作只对处于活动状态的观察者执行,如果观察者处于非活动状态,则直接退出该方法,接着会调用观察者的shouldBeActive
方法:
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
顾名思义,该方法就是判断该观察者是否应该处于活动状态,为了防止观察者的活动状态没有及时更新,直接返回观察者观察的组件是否是可见的,如果观察者不应该处于活动状态,那么就调用观察者的activeStateChanged(false)
更新状态后退出方法,否则就会判断版本号,这里解释一下版本号的作用:
LiveData
有一个版本号,观察者也有一个最后版本号,每当LiveData
的数据发生变化时,版本号都会+1,而每次更新观察者的数据时,都会将观察者的最后版本号的值置为LiveData
的当前版本号,所以如果观察者的最后版本号的值为LiveData
的当前版本号相等,则表示观察者拿到的数据是最新的。
所以这里就会判断观察者的最后版本号如果不小于LiveData
的当前版本号,那么观察者的数据就是最新的,就不需要更新,直接退出方法,否则就将最后版本号的值值为LiveData
的当前版本号,再更新数据,更新数据就是调用observer
的onChanged
方法。
再回到dispatchingValue
方法,我们这里传入的观察者不为空,所以只需要更新该观察者的数据。
跳得有点远,再回到观察者的的onStateChanged
,前面讲的是activity
生命周期为destroyed
时的流程,当不为destroyed
时,则会先调用shouldBeActive()
更新当前的活动状态,再调用activeStateChanged
方法,而这个方法前面也已经讲过了,这里就不再赘述了。
到这里再总结一下,当组件生命周期发生变化时,首先判断是否为销毁状态,是的话就将观察者从LiveData
和Lifecycle
的观察者列表中删除。否则就会判断组件生命周期变化是否导致可见性发生了变化,是的话就更新观察者当前的活动状态,如果是从非活动状态转为活动状态,LiveData
还需要向该观察者分发最新数据,观察者再根据版本号来决定是否需要更新。
LiveData更新数据时观察者是如何工作的
LiveData
更新数据是从setValue
方法开始的:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
这个方法很简单,首先这个方法只能在主线程调用,接着会将版本号+1,然后更新数据,最后再将数据分发给所有观察者。
接着再看一下另一个更新数据的方法postValue
:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
这里首先会通过加锁判断是否有其他子线程在更新,因为子线程更新数据是先将数据赋值给mPendingData
以后再拿着mPendingData
更新的,更新以后又会将mPendingData
设为NOT_SET
(其实不是这样的,先这样说比较好理解,后面会分析),所以如果mPendingData
为NOT_SET
,则表示当前线程可以更新,然后将value
赋值给mPendingData
以后再执行更新操作,否则则表示当前有其他线程正在更新,那么就把value
赋值给mPendingData
,让这个正在更新的线程来帮自己更新,自己直接退出就行了,我们现在看一下是如何更新的:
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
public static ArchTaskExecutor getInstance() {
if (sInstance != null) {
return sInstance;
}
synchronized (ArchTaskExecutor.class) {
if (sInstance == null) {
sInstance = new ArchTaskExecutor();
}
}
return sInstance;
}
很容易看出是一个单例模式,返回一个ArchTaskExecutor
对象,看一下它的相关成员变量和构造函数:
private TaskExecutor mDelegate;
@NonNull
private TaskExecutor mDefaultTaskExecutor;
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
这里可知mDelegate = mDefaultTaskExecutor = new DefaultTaskExecutor()
;
接下来看一下它的postToMainThread
函数:
@Override
public void postToMainThread(Runnable runnable) {
mDelegate.postToMainThread(runnable);
}
可以看出这是一个静态代理模式,代理给mDelegate
执行了,而mDelegate
又是DefaultTaskExecutor
类的实例,进入DefaultTaskExecutor
的postToMainThread
方法:
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = createAsync(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
这里会通过DLC获取一个Handler
对象mMainHandler
:
private static Handler createAsync(@NonNull Looper looper) {
if (Build.VERSION.SDK_INT >= 28) {
return Handler.createAsync(looper);
}
if (Build.VERSION.SDK_INT >= 16) {
try {
return Handler.class.getDeclaredConstructor(Looper.class, Handler.Callback.class,
boolean.class)
.newInstance(looper, null, true);
} catch (IllegalAccessException ignored) {
} catch (InstantiationException ignored) {
} catch (NoSuchMethodException ignored) {
} catch (InvocationTargetException e) {
return new Handler(looper);
}
}
return new Handler(looper);
}
其实就是一个主线程的Handler
,然后再在主线程执行runnable
,这个runnable
就是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);
}
};
最后还是调用了setValue
方法更新数据,这里要解释一下为什么之前说更新以后又会将mPendingData
设为NOT_SET
的说法不对,看完上面这个代码就明白了,他这里是将mPendingData
设为NOT_SET
以后才更新数据的,之前说如果当前线程试图更新数据时发现有另外一个线程正在更新数据,那么就会将值交给mPendingData
以后就交给另一个线程不管了,它判断是否有另一个线程在更新数据的依据是mPendingData
是否不为NOT_SET
,意思就是说如果mPendingData
不为NOT_SET
那么另一个线程的更新的值是可以改变的,如果为NOT_SET
,那么表示此时没有更新操作,或者更新操作的值已经无法改变了,那么就要自己亲自执行更新操作了,从代码中就能看出来,当将mPendingData
的值赋给newValue
以后,再怎么改变mPendingData
的值也无法改变此次更新的结果了。
这就是LiveData
的工作原理,个人感觉相对于Lifecycle
要更好理解。
如果有什么不正确的地方欢迎指正!