上一篇文章 中分析了ViewModel的源码,其中提到了viewmodel要配合着LiveData来一起使用,那么今天来分析一下LiveData的源码,看看怎么用,有什么注意点。
第一部分:源码头文件翻译
/**
* LiveData is a data holder class that can be observed within a given lifecycle.
//这是一个可以被lifecycle对象用来观察数据变化的类。
* This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
//这就意味着一个被观察者可以被添加在多个lifecycleOwner(观察者)中
* this observer will be notified about modifications of the wrapped data only if the paired
* LifecycleOwner is in active state.
//如果这个LifecycleOwner是处于活跃状态,才会收到被观察者数据改变的通知。
* LifecycleOwner is considered as active, if its state is
* {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}. An observer added via
//当观察者初始start/resume状态事,表示观察者是活跃状态。
* {@link #observeForever(Observer)} is considered as always active and thus will be always notified
* about modifications.
//如果调用observeForever方法添加的,那么观察者会被认为永远是活跃状态。
* For those observers, you should manually call
* {@link #removeObserver(Observer)}.
//对于这些观察者,你应该(不用的时候)主动调用移除操作。
* <p> An observer added with a Lifecycle will be automatically removed if the corresponding
//如果这个观察者是Lifecycle或其子类,那么就会自动移除掉,不需要手动移除。
* Lifecycle moves to {@link Lifecycle.State#DESTROYED} state. This is especially useful for
* activities and fragments where they can safely observe LiveData and not worry about leaks:
* they will be instantly unsubscribed when they are destroyed.
//这个对于activity或者fragment是非常有用的,当他们被销毁前会自动删除。
*
* <p>
* In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
* to get notified when number of active {@link Observer}s change between 0 and 1.
//当观察者处于不同的状态时,livedata会调用onActive和onInactive方法。
* This allows LiveData to release any heavy resources when it does not have any Observers that
* are actively observing.
//当没有任何观察者时,这个将允许liveData释放一些重的资源
* <p>
* This class is designed to hold individual data fields of {@link ViewModel},
* but can also be used for sharing data between different modules in your application
* in a decoupled fashion.
//这个类的设计初衷是用来配合ViewModel一起使用的,当然也可以用来在不同的类或者不同的模块之间传递数据
* @param <T> The type of data held by this instance
* @see ViewModel
*/
我们可以知道如下几点:
1.这个类可以用来实现不同类、不同模块之间数据的传递
2.如果观察者不是Lifecycle的子类,那么需要我们手动解除他们之间的关系,如果是则无需关心
3.只有观察者处于活跃状态时,才会接收到数据改变的通知,当然也可以设置为任何时候都接收通知
4.这个类最初是设计配合viewmodel来实现MVVM架构的
第二部分:源码解析
LiveData是一个抽象类,我们如果使用需要用他的子类,这里我们来分析子类 MutableLiveData 的用法,因为这个类基本上就是完全继承LiveData,没有做任何额外操作:
public class MutableLiveData<T> extends LiveData<T> {
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);
}
}
我们先来看如何使用:
public class TextActivity extends ComponentActivity {
private MutableLiveData<String> mLiveData;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//1.创建对象
mLiveData = new MutableLiveData<String>();
//2(3).添加观察者
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
//4.接收到发送的数据
}
});
//3(2).发送数据
mLiveData.setValue("11111");
//或者
mLiveData.postValue("2222");
}
}
1.创建对象
2.添加观察者
3.发送数据
4.观察者接收数据
其中2和3顺序可以颠倒,如果颠倒则为粘性事件
创建对象:
public LiveData() {
//初始化为Object
mData = NOT_SET;
//初始值为-1
mVersion = START_VERSION;
}
添加观察者:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//1.判断是否为主线程,如果不是则抛错误
assertMainThread("observe");
//2.判断activity或者fragment是否被销毁了
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//3.创建一个LifecycleBoundObserver 对象,这个对象很关键
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//4.以观察者回调为key,放入hashmap中,如果重复添加,则报错
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//5.activity或者fragment中获取Lifecycle,再保存wrapper
owner.getLifecycle().addObserver(wrapper);
}
1.判断是否为主线程,天剑观察者必须要在主线程中执行:
//2(3).添加观察者
mLiveData.observe(this, new Observer<String>() {
@Override
public void onChanged(String s) {
//4.接收到发送的数据
}
});
2.判断activity或者fragment是否被销毁了
3.创建LifecycleBoundObserver,参数为activity或fragment和回调
4.以回调为key,LifecycleBoundObserver为value,保存到SafeIterableMap(双向链表)中,如果为重复添加则报错
5.第三步创建的LifecycleBoundObserver 添加到观察activity或者fragment的生命周期集合中,也就是说LifecycleBoundObserver 可以接收activity的生命周期回调了。
重点关注第3步:
//LiveData的内部类,ObserverWrapper 的子类
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//判断activity是否为活跃状态
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//activity的生命周期改变监听回调
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
//如果activity被销毁了,则将观察者从回调中移除掉,这就是为什么我们无需主动移除原因
if (currentState == DESTROYED) {
//同时会调用detachObserver方法
removeObserver(mObserver);
return;
}
//判断当前activity状态是否和原来的不同,不同则回调父类ObserverWrapper中activeStateChanged方法
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
//将自己从activity的生命周期观察者队列中移除
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
这个类监听activity的生命周期主要做了如下操作:
1.只有activity的生命周期处于start之后才说明是处于活跃状态
2.当activity的生命周期改变的时候会调用onStateChanged方法,如果activity是销毁了,则将我们添加的回调移除掉,同时也会将activity的生命周期观察者从activity中移除掉,这也就为什么我只需要添加观察者,无需移除的原因。如果当前activity的状态和上一个状态不一致则,调用activeStateChanged方法,重点看看这个方法:
void activeStateChanged(boolean newActive) {
//如果activity都是处于活跃或者非活跃状态,则不需要回调,也就是说只有activity状态由活跃到非活跃状态或者反之,才需要继续执行下面操作
if (newActive == mActive) {
return;
}
mActive = newActive;
//统计activity的活跃状态次数,如果由0-1>则调用onActive方法,否则调用onInactive方法
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
//如果activity处于start状态之后,则调用这个方法
dispatchingValue(this);
}
}
只有activity处于活跃状态改变时,才会继续执行,如果activity处于start状态之后,才会调用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;
}
private void considerNotify(ObserverWrapper observer) {
//activity不是处于活跃状态,返回
if (!observer.mActive) {
return;
}
//再次检查activity是否处于活跃状态,不是则返回
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//ObserverWrapper 中最后一个版本是否大于当前版本,大于等于说明已经执行过了,无需重复执行,当前版本mVersion 会随着我们调用setValue或者postValue方法+1
if (observer.mLastVersion >= mVersion) {
return;
}
//重新给观察者最近版本赋值
observer.mLastVersion = mVersion;
//调用回调方法
observer.mObserver.onChanged((T) mData);
}
具体分析逻辑代码里写了,就不再赘述,总结一下:
1.将观察者保存起来
2.观察者和activity的生命周期绑定,观察activity的生命周期,销毁则自动解绑,接触耦合关系
3.activity的生命周期发生改变了,并且处于start状态及之后,则会校验最后一次执行回调的版本号是否大于等于当前版本号,如果小于则执行观察者回调
这里我们也可以知道livedata默认是发送粘性事件的,也就是说我们可以先发送事件,再添加观察者
再来看看发送数据方法:setValue
@MainThread //必须在主线程执行
protected void setValue(T value) {
//判断是否为主线程
assertMainThread("setValue");
//记录数据版本号,用来和观察者接收版本号对比,防止多次发送同一个数据,也用来发送粘性事件
mVersion++;
mData = value;
//直接调用分发数值方法
dispatchingValue(null);
}
方法很简单:必须在主线程执行,增加数据版本号,调用上面分析的分发值方法(查找观察者,校验观察者生命周期状态,校验数据版本号和观察者发送版本号,回调方法)
再来看看另一个发送数据的方法:postValue
protected void postValue(T value) {
//校验是否发送的内容为默认值object,是则放弃
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//切换到主线程发送数据
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
先看看ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable):
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = createAsync(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
就是用handler切换到了主线程,执行runnable任务:
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方法,所以postValue方法可以在任何线程中调用,回调还是在主线程中执行。源码分析完毕。
第三部分:不同类(activity或fragment)之间数据传值
思路1:LiveData设置为静态类变量
优缺点:简单,也不会发生内存泄漏问题,但是不方便管理
思路2:写一个LiveData工具类,用hashmap保存所有的LiveData,实现全局共享
优点:方便管理
我们使用思路2来实现一下:
public enum LiveDataUtils {
INSTANCE;
public static LiveDataUtils getsInstance() {
return INSTANCE;
}
private HashMap<String, MutableLiveData> mLiveDataMap = new HashMap<>();
public <T> MutableLiveData<T> getLiveData(Activity activity, Class<T> value) {
MutableLiveData<T> mutableLiveData = mLiveDataMap.get(activity.getClass().getSimpleName() + value.getSimpleName());
if (null == mutableLiveData) {
mutableLiveData = new MutableLiveData<T>();
mLiveDataMap.put(activity.getClass().getSimpleName() + value.getSimpleName(), mutableLiveData);
}
return mutableLiveData;
}
public <T> MutableLiveData<T> getLiveData(Fragment fragment,Class<T> value) {
MutableLiveData<T> mutableLiveData = mLiveDataMap.get(fragment.getClass().getSimpleName() + value.getSimpleName());
if (null == mutableLiveData) {
mutableLiveData = new MutableLiveData<>();
mLiveDataMap.put(fragment.getClass().getSimpleName() + value.getSimpleName(), mutableLiveData);
}
return mutableLiveData;
}
public <T> MutableLiveData<T> getLiveData(Class cla, Class<T> value) {
MutableLiveData<T> mutableLiveData = mLiveDataMap.get(cla.getSimpleName() + value.getSimpleName());
if (null == mutableLiveData) {
mutableLiveData = new MutableLiveData<>();
mLiveDataMap.put(cla.getSimpleName() + value.getSimpleName(), mutableLiveData);
}
return mutableLiveData;
}
}
这样只要用的时候就可以直接获取,添加回调,其他任何页面发送事件就可以了。
第四部分:使用过程中的bug
1.如果A activity不是栈顶activity,A中添加了观察者,B页面多次setValue或者postValue,那么A activity只会响应最后一次数据,前面的全部都被覆盖掉了。
解决方案:
LiveDataUtils.getsInstance().getLiveData(this,Integer.class).observeForever( new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
}
});
使用observeForever 替代observe方法,并且需要在页面ondestory方法中添加,remvove方法,否则会发生内存泄漏。
LiveDataUtils.getsInstance().getLiveData(this,Integer.class).removeObserver();
2.去掉粘性事件,有些时候我们不想要粘性事件,那么可以参考