Android源码解析:LiveData
2018-12-17 本文已影响2人
小村医
概述
简单地来说,LiveData就是一个持有数据的类。
LiveData中的数据可以被观察者订阅,当数据被修改时通知观察者。观察者包括Fragment、Activity以及Service等。
LiveData能够感知观察者的生命周期。只有在观察者处于激活状态(STARTED之后的状态)才会收到数据更新;并在onDestroy时自动解注册观察者,避免崩溃,且减少内存泄露。
使用
使用LiveData子类MutableLiveData,维护一个String类型的数据:
public class MyViewModel extends ViewModel{
private MutableLiveData<String> mData;
public MutableLiveData<String> getData() {
if (mData == null) {
mData = new MutableLiveData<>();
}
return mData;
}
public void setData(String data){
//更新livedata中的值
mData.setValue(data);
}
}
接着注册观察者:
public class LiveDataFragment extends Activity{
private MyViewModel mViewModel;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
mViewModel.getData().observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String data) {
//LiveData数据变化后的回调
}
});
}
}
主要类
LiveData类图.png源码分析
从以下几个方面对源码进行分析:
1. 如何注册观察者
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// 当前Activity/Fragment为destory状态时忽略
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//mObservers(一个类似Map的容器)的putIfAbsent()方法用于判断容器中的observer是否有已经和wrapper关联,
//如果已关联则返回关联值,否则关联之后并返回wrapper
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;
}
//使用上面new的wrapper对象监听Activity/Fragment的生命周期
owner.getLifecycle().addObserver(wrapper);
}
LifecycleBoundObserver继承自ObserverWrapper对象并实现GenericLifecycleObserver接口,当组件的生命周期发生变化后会通过onStateChanged()方法回调过来通知ObserverWrapper生命周期变化
2. 如何监听Activity/Fragment的生命周期
通过上面的分析,可以知道组件生命周期的观察者就是LifecycleBoundObserver对象,下面我们看一下LifecycleBoundObserver具体实现:
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() {
// 判断组件是否active
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//组件destory后移除监听者
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
当组件生命周期发生变化时,onStateChanged()方法会被调用。如果当前处于Lifecycle.State.DESTROYED时,会自动将观察者移除;若当前处于ACTIVE状态,则继续执行,调用activeStateChanged方法,该方法在ObserverWrapper中实现
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
//设置当前监听的组件是否active,只有处于active状态的组件才会通过观察者模式通知组件数据变化
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);
}
}
最后调用的是dispatchingValue()进行数据变化时的消息通知
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
//组件生命周期变化时initiator不为空,considerNotify直接调用Observer的onChanged方法
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//遍历所有观察者调用onChanged通知数据变化
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
3. setValue()或postValue()方法后,通知观察者更新数据
LiveData提供了两种改变数据的方法:在主线程调用的setValue()方法,以及在子线程中调用的postValue()方法。现在看下两个方法的具体实现:
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
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() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//最终通过Handler在主线程调用setValue
setValue((T) newValue);
}
};
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}