Android AAC第二篇 LiveData的源码解析
Posted 宿罪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android AAC第二篇 LiveData的源码解析相关的知识,希望对你有一定的参考价值。
前言
首先看一下如下一个简单的使用例子,本文范例使用Kotlin语言进行介绍,Java版的类似,不懂的可以留言问我哈。
// 1.创建LiveData
var loginLiveData:MutableLiveData<LoginEntity> = MutableLiveData<LoginEntity>()
// 2.观察LiveData
loginLiveData.observe(this, Observer
Log.e(TAG,"loginEntity:$it")
if(!TextUtils.isEmpty(it.token))
// 成功
Toast.makeText(mContext,"login success", Toast.LENGTH_SHORT).show()
startActivity(Intent(mContext,MainActivity::class.java))
else
// 失败
Toast.makeText(mContext,"login failure", Toast.LENGTH_SHORT).show()
)
// 3.触发数据改变
loginLiveData.value = response.data
LiveData的使用需要经过以上三个步骤
- 第一步传入一个泛型实体类型T创建一个LiveData(通常在我们的ViewModel中),这个T通常就是我们自己定义的实体类,如在Kotlin我们中采用data class;
- 第二步在我们的MainFragment或者Activity等涉及到UI的地方调用observer方法观察数据源;
- 第三步我们需要去触发数据源的改变,通常是我们通过异步操作去网络加载或者本地数据库查询到的数据通过
setValue
方法设置给我们的LiveData
,这时我们的UI也就跟随着改变了。
在以上例子中,LoginEntity是我们自己定义的一个实体类,MutableLiveData是LiveData的子类,它很简单,仅是继承了LiveData将LiveData的postValue(T value)
和setValue(T value)
两个方法的访问权限由protected改为public,也就是说它的作用是公开LiveData的两个关键方法postValue(T value)
和setValue(T value)
。通过LiveData的observer方法可以监听到LiveData的数据改变,这个数据改变的触发点就是postValue(T value)
和setValue(T value)
。后面我们从源码的角度出发去分析一下LiveData的工作原理。
源码解析
我们先把握LiveData的整体工作原理,一些细节放到后面再分析,我们先从LiveData的入口出发,先看看observe
方法的源码:
@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);
首先我们看到这方法上面有一个注解@MainThread,它是一个标记注解,没有任何实际作用,仅仅是告诉我们这个方法需要在主线程中调用。这个方法先是判断这个方法是不是在主线程中回调,如果不是将会抛出IllegalStateException("Cannot invoke " + methodName + " on a background" + " thread")
异常,然后创建了一个wrapper用来包裹owner和observer,然后将这个observer放入mObservers
中保存起来,如果已经这个observer已经保存过,并且这个observer没有和当前的owner绑定那么将会识别为同一个observer依附在不同的owner下将会抛出异常,如果已经添加过这个observer并且是同一个owner,那么将会不理睬这次操作,最后将observer和当前的owner的生命周期绑定。
从这个方法的源码中我们知道:
- 我们不能将同一个observer依附在不同的owner下,如在Activity和Fragment中使用同一个observer;
- 不能在子线程中调用observe方法;
- observe方法中绑定了owner的生命周期,如果当前的owner的生命周期为DESTROYED,则忽略此次观察。
接下来我们看看setValue()
方法,也就是触发数据源改变的地方
@MainThread
protected void setValue(T value)
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
这个方法将value保存在mData中,接着看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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); )
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated)
break;
while (mDispatchInvalidated);
mDispatchingValue = false;
这个方法通过mDispatchingValue
和mDispatchInvalidated
变量如果当前方法在多个线程中同时访问,那么后面访问的方法会使得do循环体内的代码终止上次执行(break)并重新执行一遍,接下来我们看看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;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
这个方法中首先判断了传入的observer的激活状态,如果未激活则不响应,如果当前的observer不需要被激活,那么会执行它的activeStateChanged
方法,最终调用observer的onChange
方法将我们在observe方法中保存的data数据传回。
这个是setValue()
方法的执行流程,我们还有一个postValue()
方法,接下来我们看看postValue
protected void postValue(T value)
boolean postTask;
synchronized (mDataLock)
postTask = mPendingData == NOT_SET;
mPendingData = value;
if (!postTask)
return;
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
这个方法通过postToMainThread将数据通知操作切换到了主线程,通过mPendingData变量标记当前主线程是否执行完数据刷新操作,我们看看mPostValueRunnable
private final Runnable mPostValueRunnable = new Runnable()
@Override
public void run()
Object newValue;
synchronized (mDataLock)
newValue = mPendingData;
mPendingData = NOT_SET;
//noinspection unchecked
setValue((T) newValue);
;
在主线程执行完成后将mPendingData 置为NOT_SET,如果当前主线程还没处理完这次数据更新,那么后面通过postValue
更新的值将会被忽略,后面调用了setValue()
方法,可以看到postValue
内部将数据的更新操作切换到主线程。
经过以上分析,LiveData的工作原理是内部维持一个Observer的列表,通过observe
方法添加一个观察者,在observe
方法中绑定owner的生命周期,然后在调用setValue
方法的时候通知Observer数据源发生改变,利用的是观察者模式。下面我们看看LiveData是怎么和owner绑定生命周期的。
我们在observe方法中可以看到owner.getLifecycle().addObserver(wrapper);
这里我们先看看这个wrapper类LifecycleBoundObserver.java
LifecycleBoundObserver.java
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver
@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(LifecycleOwner source, 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);
首先我们看这个类的类结构,发现它实现的GenericLifecycleObserver
接口,该接口是LifecycleObserver 的子类,所以当前的wrapper类实际上是一个LifecycleObserver ,所以可以调用owner.getLifecycle().addObserver(wrapper)
来绑定生命周期。
GenericLifecycleObserver.java
public interface GenericLifecycleObserver extends LifecycleObserver
/**
* Called when a state transition event happens.
*
* @param source The source of the event
* @param event The event
*/
void onStateChanged(LifecycleOwner source, Lifecycle.Event event);
LifecycleBoundObserver 继承于ObserverWrapper.java,我们看看ObserverWrapper.java的activeStateChanged
方法
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);
可以发现其内部维持了一个变量,这个变量用来记录当前Observer的激活状态,在当前的激活数量由0变成1的时候会调用onActive()
方法,当激活数量由1变成0的时候会调用onInactive()
方法,我们再看看LifecycleBoundObserver
的shouldBeActive
方法
@Override
boolean shouldBeActive()
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
可以发现,LiveData就是在这里判断当前是否需要通知Observer响应数据的改变(回调onChanged()
方法),这里至少要求生命周期为started。接下来我们看看生命周期绑定的最后一个很关键的方法onStateChanged()
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event)
if (mOwner.getLifecycle().getCurrentState() == DESTROYED)
removeObserver(mObserver);
return;
activeStateChanged(shouldBeActive());
在上一篇文章【Android AAC】第一篇 Lifecycle的源码解析中我们知道了GenericLifecycleObserver
的onStateChanged()
会在Fragment中回调,可以看到,在onStateChanged
方法中,如果当前的owner的生命周期为DESTORYED,那么将会移除这个观察者,也就是说LiveData会自动解除绑定,而不会造成内存泄漏。如果是其他的生命周期,则会调用activeStateChanged
判断当前的生命周期是否需要响应响应的事件,这里我们回归一下LiveData的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;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
这个方法是在setValue方法中会调用的,也就是数据源发生改变的时候会回调这个方法,在这个方法里面判断了当前observer是否需要响应这次数据源的改变。并且根据当前的LiveData的observer激活数量来判断当前LiveData是否被激活或是停止激活,并且会回调LiveData的onActive
和onInactive
方法,不过这两个方法是protected
的,我们可以像MutableLiveData一样通过继承LiveData将onActive
和onInactive
覆盖为public暴露出去。仔细观察发现还有一个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 != null && existing instanceof LiveData.LifecycleBoundObserver)
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
if (existing != null)
return;
wrapper.activeStateChanged(true);
这方法创建的wrapper类为AlwaysActiveObserver
,它表示忽略owner的生命周期,不会自动移除这个观察者,总是会响应数据源的改变,所以,这个方法需要我们手动管理observer的解除绑定操作。
private class AlwaysActiveObserver extends ObserverWrapper
AlwaysActiveObserver(Observer<? super T> observer)
super(observer);
@Override
boolean shouldBeActive()
return true;
经过上面的分析,我们知道LiveData的工作原理如下:
- 在其内部维持了一个List,用来保存observer,每个observer都和传入的owner的生命周期绑定,这个owner通常为Activity或是Fragment;
- 外部通过LiveData的
setValue
或者postValue
方法更新数据源,在这个方法中会分发新的数据源到需要每个观察者,同时会判断当前的观察者是否需要响应响应的事件。 - LiveData内部通过observer和owner的生命周期绑定,并且通过
LifecycleBoundObserver
的onStateChanged
方法判断并移除响应的observer避免了内存泄漏。这个onStateChanged
方法是GenericLifecycleObserver
接口的一个方法,由系统在相应的生命周期中回调。
总结:
LiveData通过观察者模式和Lifecycle来根据owner的生命周期来对数据源的改变做出响应,其内部在owner处于DESTORYED状态的时候会自动移除响应的observer避免了内存泄漏。
以上是关于Android AAC第二篇 LiveData的源码解析的主要内容,如果未能解决你的问题,请参考以下文章