来个例子
data.observe(this, observer)
data.setValue(1)
上述代码,监听者会触发一次,我们来看看其中的缘由
在setValue里会给mVersion 成员变量加一,意味着数据的版本 加一,这个mVersion默认值是-1
mVersion++;
mData = value;
dispatchingValue(null);
然后追查dispatchingValue函数的调用链,看它 是如何通知到监听者, 因为当初传的是空,所以会执行else语句
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
}
}
看看mObservers是什么,在 oberser函数里,把监听者和生命周期持有者封装存放在mObservers,所以遍历它来给所有注册的监听者传递最新的数据
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
这个considerNotify里,监听者有一个mLastVersion 成员变量,默认值是-1,与LiveData的mVersion相比较,如果大于等于mVersion,就表示数据版本更新,无需触发监听,否则就是把mVersion赋值给mLastVersion, 并且触发监听。
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
首先展示一个最简单能体现粘性消息的例子
data.setValue(1)
data.observe(this, observer)
上述代码依旧 能够触发监听者的回调,我们看看observe函数做了什么,把监听者 并和lifecycle持有者一起打包
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
owner.getLifecycle().addObserver(wrapper);
找找 getLifecycle()获取的实例,我们需要从AppCompatActivity开始找,最后在FragmentActivity找到
final LifecycleRegistry mFragmentLifecycleRegistry = new LifecycleRegistry(this);
然后来看看它的addObserver函数,它调用了这么一行代码,用于传递事件,继续追查
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
给 封装了lifecycle持有者发送数据,看 mLifecycleObserver实例在哪
mLifecycleObserver.onStateChanged(owner, event);
得继续 看 lifecycleEventObserver
ObserverWithState(LifecycleObserver observer, State initialState) {
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
这个判断很多,我 们需要 清楚这个observer的实例是啥
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver
public interface GenericLifecycleObserver extends LifecycleEventObserver
好了,我们再来看看lifecycleEventObserver 函数,说白了就是返回传进去的 实例了
boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
if (isLifecycleEventObserver) {
return (LifecycleEventObserver) object;
}
然后看看onStateChanged函数调用了啥
activeStateChanged(shouldBeActive());
继续
dispatchingValue(this);
还继续,这个函数就很眼熟了,里面进行了版本比较,和触发更新,
considerNotify(initiator);
首先说说setValue,它的元注解MainThread规定了此函数在主线程执行,赋值时,版本加一
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
我再给出一个使用的例子,你们 猜猜,触发监听多少次,结果是一次,为何,我们接着看看 dispatchingValue函数
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.v("zzw","onCreate")
data.observe(this, observer)
data.setValue(1)
data.setValue(2)
}
dispatchingValue最后会执行 considerNotify函数,这个函数虽然我之前贴出过几次,但没有说到它真正的厉害之处。
首先需要提醒的是 LiveData不只是一个简单的被监听者,它依赖于生命周期。
我在 if(!observer.mActive)这里打了断电,第一次 mActive为false,第二次为false,第三次为true。我调用了 两次setValue,为何有 三次调用到这里,说明还有其他 地方调用了。
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
这里我对onStart和onResume都复写,打日志,再运行一次。这个说明第三次是在 onStart和onResume之间
onCreate
onStart
2
onResume
那我把 setvalue的代码放在onStart里,结果一样,如果放在onResume里,成功
onCreate
onStart
onResume
1
2
这里我再次打断点,considerNotify调用了三次,而且第一次因为LiveData的版本是-1,所以没有更新 数据。那这个多出的
一次调用是在onResume的开头。
首先我们看看,我们 在onStart和onCreate里的considerNotify调用是如何被中断的。因为前面打过断点,是因为observer.mActive为false,而这个变量默认没有赋值,也就是false,找找这个observer的 来源,来源是 LiveData.observer函数
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
这个observer的类是LifecycleBoundObserve,他有一个函数,看起来是分发状态,并且调用了父类的函数
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
这里可以看出 mActive的值由传入的newActive决定,也就是 shouldBeActive函数决定
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
if (mActive) {
dispatchingValue(this);
}
}
这个shouldBeActive函数实质内容就是, 判断当前宿主的生命周期是否大于等于 onStart,如果 是的就返回true
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
所以我们之前的数据 传不到 监听者,是因为生命 周期不到。而每次生命周期变化,都会触发 onStateChanged函数
mLifecycleObserver.onStateChanged(owner, event);
setValue的总结:值传递到监听者,有生命周期的限制(onStart以上,onDestroy以下)并且每次生命周期变化都会试着将值传递给监听者。
postValue与setValue最大的 不同是,它可以在子线程传递数据。
而在子线程之间共享数据,最大的问题是线程同步,防止出现脏数据的问题
首先看看postValue,在同步锁下它先把 值传给 mPendingData,如果我们是连调用几个postValue, 因为当前mPendingData已经被赋值了,所以就被return了,看看 postToMainThread做了啥
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
因为这是一个代理模式,我找找他的实现类
private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
使用创建了一个在主线程运行的Handler,来运行runable
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
我们再回个头看看,运行的runable的内容,它把mPendingdata的值取出,然后赋予默认值,然后调用setValue。 这里需要 特别说明的是,之前也说过 连续调用几次postvalue, 只有第一次调用会 发送这个Runnable,但是这个 mPendingdata每次都会被赋值,所以这个节约了刷新次数。
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
1.如果想让连续多次调用setValue,每次都触发更新,需要在onResume函数里调用
2.如果不想让分发LiveData设置的初始值,建议在设置初始值前,添加观察者