LiveData是Android Architecture Components 其中的一个组件。主要用于更新UI数据和组件之间传值。
1、LiveData是一种持有可被观察数据的类。它通过观察者模式实现了数据变化的动态通知,即当观察者生命周期处于活跃状态时,能够感知数据的变化。
2、能够感知生命周期,内部通过Lifecycle来感知生命周期,在Activity、Fragment、Service中当对应生命周期为Destroy的时候,会销毁观察者,避免内存泄露;
LiveData的简单使用LiveData的使用十分方便,只需要简单的三步:
1、创建LiveData对象,LiveData是抽象类,所以需要创建它的子类MutableLiveData;
2、设置观察者observe,第一个参数是LifecycleOwner对象,第二个是观察者监听,当数据改变的时候会在onChanged方法内做出响应;
3、设置数据,通过postValue或者setValue方法来更新数据;
public class MainActivity extends AppCompatActivity { private MutableLiveData liveData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1.创建LiveData对象 liveData = new MutableLiveData(); // 2.添加观察者 liveData.observe(this, new ObserverLiveData原理() { @Override public void onChanged(String s) { // 提示数据变化 Toast.makeText(MainActivity.this, s, Toast.LENGTH_SHORT).show(); } }); findViewById(R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 3.改变数据 liveData.postValue("测试"); } }); } }
一、LiveData是如何实现观察者订阅,并发送事件的?
LiveData通过observe和observeForever来订阅观察者,查看源码可以看到
@MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) { assertMainThread("observe"); ///1、判断当前状态是否是DESTROYED,如果不是则添加观察者 if (owner.getLifecycle().getCurrentState() != State.DESTROYED) { ///2、创建LifecycleBoundObserver类 LiveData.LifecycleBoundObserver wrapper = new LiveData.LifecycleBoundObserver(owner, observer); ///3、将观察者和LifecycleOwner添加到map中一一对应 LiveData .ObserverWrapper existing = (LiveData.ObserverWrapper)this.mObservers.putIfAbsent(observer, wrapper); // 对应观察者只能与一个owner绑定 if (existing != null && !existing.isAttachedTo(owner)) { throw new IllegalArgumentException("Cannot add the same observer with different lifecycles"); } else if (existing == null) { // 当不存在的时候添加LifecycleObserver owner.getLifecycle().addObserver(wrapper); } } }
1、源码首先判断当前状态是否是DESTROYED,如果不是则不会注册当前;
2、创建LifecycleBoundObserver类,该类实现了生命周期与观察者的绑定,在此类中有个onStateChanged方法如下,onStateChanged方法中会在生命周期状态发生改变时判断当前状态是否是DESTROYED,如果是就移除当前监听者,避免内存泄露。
public void onStateChanged(LifecycleOwner source, Event event) { // 当生命周期处于DESTROYED的时候移除当前订阅者 if (this.mOwner.getLifecycle().getCurrentState() == State.DESTROYED) { LiveData.this.removeObserver(this.mObserver); } else { // 非DESTROYED的时候进行状态改变 this.activeStateChanged(this.shouldBeActive()); } }
LifecycleBoundObserver类继承ObserverWrapper类,ObserverWrapper又是观察者的包装类。
LifecycleBoundObserver类通过实现了GenericLifecycleObserver接口->LifecycleEventObserver接口,最终实现了LifecycleEventObserver接口,所以下面将wrapper添加到Lifecycle的监听中。
owner.getLifecycle().addObserver(wrapper);
3、LiveData中创建了一个Map来存储每一个观察者和生命周期的包装类,并且会判断当前对应观察者只能与一个owner绑定。
二、postValue和setValue过程分析
LiveData可以通过postValue和setValue来设置数据,当请求完网络数据的时候,就可以调用postValue或setValue来设置数据,当然postValue是可以在任意线程进行调用,setValue只能在主线程调用。postValue最终也是调用setValue方法。
下面分析一下postValue的源码执行过程:
MutableLiveData类中的postValue和setValue都是调用了父类(LiveData)的方法。直接查看LiveData的postValue方法:
protected void postValue(T value) { boolean postTask; synchronized(this.mDataLock) { postTask = this.mPendingData == NOT_SET; this.mPendingData = value; } if (postTask) { // 转到主线程去执行,所以postValue方法可以在任意线程执行 ArchTaskExecutor.getInstance().postToMainThread(this.mPostValueRunnable); } }
源码中最终会转到主线程去执行,所以postValue方法可以在任意线程执行,再查看mPostValueRunnable源码:
public LiveData() { this.mData = NOT_SET; this.mPendingData = NOT_SET; this.mVersion = -1; this.mPostValueRunnable = new Runnable() { public void run() { Object newValue; synchronized(LiveData.this.mDataLock) { newValue = LiveData.this.mPendingData; LiveData.this.mPendingData = LiveData.NOT_SET; } // 这里最终调用了setValue方法 LiveData.this.setValue(newValue); } }; }
在LiveData的构造方法中创建了mPostValueRunnable,并在最后调用了setValue方法。下面再看一下setValue方法:
@MainThread protected void setValue(T value) { assertMainThread("setValue"); // 版本+1 ++this.mVersion; // 将值赋值给全局变量mData this.mData = value; // 分发数据 this.dispatchingValue((LiveData.ObserverWrapper)null); }
setValue中主要做了三个事:
1、版本+1,LiveData的mVersion变量表示的是发送数据的版本,每次发送一次数据, 它都会+1;
2、将值赋值给全局变量mData;
3、调用dispatchingValue方法分发数据,dispatchingValue方法中主要调用的是considerNotify方法
private void considerNotify(LiveData.ObserverWrapper observer) { // 如果观察者处于活跃状态 if (observer.mActive) { // 判断是否应该改变状态 if (!observer.shouldBeActive()) { observer.activeStateChanged(false); } else if (observer.mLastVersion < this.mVersion) {// 当观察者的最后版本小于当前版本,表示有数据改变了 // 将当前版本跟观察者的版本进行统一 observer.mLastVersion = this.mVersion; // 触发onChange方法 observer.mObserver.onChanged(this.mData); } } }
查看shouldBeActive方法,这里通过LifeCycle的当前状态对比State.STARTED来判断,当是STARTED或者RESUMED状态时,才会触发observer的activeStateChanged方法,这时就会执行LifecycleBoundObserver中的activeStateChanged方法。
boolean shouldBeActive() { return this.mOwner.getLifecycle().getCurrentState().isAtLeast(State.STARTED); }
另外,当observer的mLastVersion(初始值为-1)版本小于LiveData的mVersion时,就表示有新数据改变了,所以就会触发onChanged方法。
三、observe和observeForever区别
observer会自动监听生命周期,当是STARTED和RESUMED的时候才会触发订阅,而observeForever则是会一直检测数据变化,只要数据变化了就会触发订阅。
@MainThread public void observeForever(@NonNull Observer super T> observer) { assertMainThread("observeForever"); // 会创建一个总是活动的观察者 LiveData.AlwaysActiveObserver wrapper = new LiveData.AlwaysActiveObserver(observer); ...... }
如源码所示,observeForever会创建一个总是活动的观察者AlwaysActiveObserver,改类继承ObserverWrapper,并实现了shouldBeActive方法,而且始终返回true,所以只要数据一改变,会触发onChanged方法。
private class AlwaysActiveObserver extends LiveData.ObserverWrapper { AlwaysActiveObserver(Observer super T> observer) { super(observer); } // 一直返回true boolean shouldBeActive() { return true; } }
而在LifecycleBoundObserver中实现了onStateChanged方法,在该方法中会根据当前状态是否为State.DESTROYED来自动移除监听者,所以observeForever则不会,所以需要在onDestroy中手动移除。
@Override protected void onDestroy() { super.onDestroy(); // 使用observeForever需要手动移除 liveData.removeObserver(MyObserver); }
四、LiveData粘性事件和数据倒灌
粘性事件:先setValue/postValue,后调用observe(),如果成功收到了回调,即为粘性事件。
数据倒灌:先setValue/postValue,后调用observe(new Obs()),至此收到了回调。然后再第二次调用observe(new anotherObs()),如果还能收到第一次的回调,则为“数据倒灌”。
大家可以看一下这篇文章:
关于LiveData粘性事件所带来问题的解决方案
组件之间传值工具类:UnPeek-LiveData
LiveDataBus
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)