相信很多人在职业生涯的面试过程中都会被问到关于LiveData相关的。
今天就来分析一下LiveData的粘性事件以及LiveData订阅与数据分发。
另外总结一下LiveDate事件事件一共有以下内容:
LiveDate粘性事件Framework源码分析
Jetpack中的状态机是如何管理生命周期
Hook实现LiveDate非粘性功能
LiveDate递归调用源码是如何做容错的
企业级LiveDateBus封装实现
腾讯T10Android笔记大全(包含(视频+文字):Android基础-性能优化-Framework-compose开源项目-音视频初中高-架构-车载-Flutter-Kotlin-Harmony OS+音视频详细文档。)
私信获取:面试
粘性事件:相对比普通事件,粘性事件支持先发送事件,再去注册订阅者。一旦完成订阅动作,这个订阅者就会接收到该粘性事件。
所以粘性其实就可以理解为观察者模式的升级,让观察者与被观察者对象之间更加的粘合。
举个栗子,我们利用livedata来做APP的全局状态管理
object GlobalState {
val jcTestNumberLd: MutableLiveData = MutableLiveData()
}
然后在 Fragment 以及 Activity 中观察该 jcTestNumberLd。
/** 观察 GlobalState 的 Activity */
class JcTestActivity : BaseVmDbActivity() {
override fun initView() {
viewBinding.incButton.setOnClickListener {
GlobalState.jcTestNumberLd.value =
if (GlobalState.jcTestNumberLd.value == null) {
1
} else {
GlobalState.jcTestNumberLd.value!!.toInt().inc()
}
}
}
override fun initObserve() {
GlobalState.jcTestNumberLd.observe(this, {
Log.e(TAG, "initObserve: jctestNumber = $it")
})
}
........
}
/** 观察 GlobalState 的 Fragment */
class EventFragment : BaseVmDbFragment() {
override fun setObservers() {
GlobalState.jcTestNumberLd.observe(viewLifecycleOwner, {
Log.e(TAG, "setObservers: jctestNumber = $it", )
})
}
........
}
注意:这里例子中的 EventFragment 并不是关联到 JcTestActivity 的。用户会先进入到 JcTestActivity,然后由用户控制进入到另一个Activity中,加载 EventFragment。
我们来执行一下以下五步操作,来看一下输出的日志。
输出结果:
E/JcTestActivity: initObserve: jctestNumber = 1
E/JcTestActivity: initObserve: jctestNumber = 2
E/JcTestActivity: initObserve: jctestNumber = 3
E/EventFragment: setObservers: jctestNumber = 3
这就是粘性事件!所以说,LiveData是粘性的。
在知道LiveData是粘性后,我不经问自己:它是怎么实现粘性的呢?
这里我们先来回顾一下EventBus粘性事件的实现原理。
EventBus在发送粘性事件时,会将这粘性事件存到一个叫做 stickyEvents 的集合中,然后等注册订阅新的观察者对象时,会去遍历该集合中的粘性事件,如果有找到对应的粘性事件,就将该粘性事件发送给该观察者。(如果你对EventBus粘性事件不熟悉,可以点击EventBus 源码解析(很细 很长)进一步了解学习。)
LiveData是不是也是以同样的原理来实现粘性的呢?
public LiveData(T value) {
mData = value;
mVersion = START_VERSION + 1;
}
/**
* Creates a LiveData with no value assigned to it.
*/
public LiveData() {
mData = NOT_SET;
mVersion = START_VERSION;
}
从 LiveData 的构造函数中可以发现有一个 mVersion 参数,它代表着 LiveData 的版本号,每当我们进行 setValue 时,都会让 mVersion 进行自增。
另外,ObserverWrapper 这个观察者包装类中也有一个 int mLastVersion = START_VERSION 版本号。
这两个版本号分别是被观察者对象与观察者对象的版本号,那这二者之间又有什么关系呢?
在判断是否通知观察者的 considerNotify(ObserverWrapper observer)方法中,会对这两个版本号进行比较。
private void considerNotify(ObserverWrapper observer) {
...省略代码...
//如果观察者的版本号 >= LiveData的版本号,就说明该观察者已经接收过该观察事件,也就不再分发。
if (observer.mLastVersion >= mVersion) {
return;
}
//反之,分发观察事件给该观察者,让其执行对应的观察动作,并更新观察者的版本号
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
概括一下:根据比对观察者对象的版本号与LiveData的版本号来判断是否分发当前版本的数据给该观察者。如果观察者对象的版本号大于等于LiveData的版本号,也就说明该观察者已经接收过当前版本的数据了,也就不需要再次分发了(等待下一次数据更新)。反之,则分发当前版本的数据给该观察者,让其执行对应的观察动作,并更新观察者的版本号,也就是更新为LiveData的版本号。
LiveData 是可观察的数据存储器类,这样也就意味着存储在LiveData中的数据是会更新的,既然是会更新的,那必定就会存在状态,即最新数据状态。
所以,当数据状态发生改变时(数据发生了更新),LiveData需要告诉所有处于活跃状态的观察者, 让其同步更新数据。这应该很好理解了,因为这就是普通事件,先注册观察者,再去更新被观察者对象,触发观察事件。
那这时,你再去新注册一个观察者对象,你认为它需不需要知道此时LiveData最新的数据呢?
答案是:需要。
因为所有的观察者,都只需要知道LiveData中存储的数据,而且是最新数据。不管我是新注册的观察者,只要你LiveData有了最新数据,就需要告诉我。而关于有无新数据,从代码上体现出来的就是,LiveData.mVersion > Observer.mLastVersion 。
这也就是粘性事件,先更新被观察者对象,触发观察事件,再去注册观察者,观察者会直接接收到该观察事件,执行对应的观察动作。
它的功能属性导致其只能是粘性的。
使用
public class LiveDataActivity extends AppCompatActivity {
MutableLiveData liveData= new MutableLiveData();
void liveDataTest(){
// 任何线程都可以发送数据
liveData.postValue("postValue");
// 只有主线程可以发送数据
// liveData.setValue("setValue")
}
void observeTest(){
//订阅
liveData.observe(this, new Observer() {
@Override
public void onChanged(String data) {
//收到数据data
}
});
//可以有多个订阅
liveData.observe(this, new Observer() {
@Override
public void onChanged(String data) {
//收到数据data
}
});
}
}
阶段一:
postValue:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
mPostValueRunnable:
volatile Object mPendingData = NOT_SET;
private int mVersion;
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:
private volatile Object mData;
private int mVersion;
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
看到这里发现,数据其实最后存到了mData中;若想发送订阅消息,肯定得添加订阅者;
阶段二:
添加订阅者,observe():
//用户使用:
//liveData.observe(this@LiveDataActivity,{
//
//})
private SafeIterableMap, ObserverWrapper> mObservers =
new SafeIterableMap<>();
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
//如果被观察者的生命周期是DESTROYED,就不添加订阅者
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
...
owner.getLifecycle().addObserver(wrapper);
}
LifecycleBoundObserver及它的父类ObserverWrapper:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
...
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
if (currentState == DESTROYED) {
removeObserver(mObserver);
return;
}
Lifecycle.State prevState = null;
while (prevState != currentState) {
prevState = currentState;
activeStateChanged(shouldBeActive());
currentState = mOwner.getLifecycle().getCurrentState();
}
}
...
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
//ObserverWrapper
private abstract class ObserverWrapper {
//传进来的观察者放这里了
final Observer<? super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<? super T> observer) {
mObserver = observer;
}
...
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
mActive = newActive;
changeActiveCounter(mActive ? 1 : -1);
if (mActive) {
dispatchingValue(this);
}
}
}
阶段三:
分发:
在阶段一setValue()时,调用了dispatchingValue(null);
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, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
...
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
到此LiveDate关于粘性事件与订阅和数据分发就讲完啦。
腾讯T10Android笔记大全(包含(视频+文字):Android基础-性能优化-Framework-compose开源项目-音视频初中高-架构-车载-Flutter-Kotlin-Harmony OS+音视频详细文档。)
私信获取:面试
更多Android面试大全总结(全文30W+字.200多个知识点.330张图.38个视频合集)
包含(视频+文字):Android基础-性能优化-Framework-compose开源项目-音视频初中高-架构-车载-Flutter-Kotlin-Harmony OS+音视频详细文档。
一丶T10级Android工程师必备基础技能
涉及:注解、泛型、Retrofit、架构动态编程技术原理、Butterknife、JavaSSit丶虚拟机丶并发内存丶Synchronize丶并发原理之线程池丶数据序列化
二丶T10工程师核心优化能力
涉及:启动优化、内存优化、启动优化速度、卡顿优化、布局优化、崩溃优化、应用启动全流程(源码深度解析)等内容.
三丶Framework
涉及:Framework通信、Framework底层服务、Framework事件机制等内容.
四丶Compose(开源项目)
五.音视频开发
涉及:C和C++基础语法,H264编码基础和进阶,H265编码原理和应用MediaCodec硬解码,Media内核源码,WeChat视频通话。初级-中-高
附带音视频开发预习资料文档
涉及:视频区,视频压缩,音视频同步,FFmpeg,OPenGL,OpenSL ES,抖音美颜滤镜,交叉编译,视频变速,FFmpeg实现音视频同步
六丶Android资深架构师
涉及:Arraylist,Okhttp,Retrofit,图片加载,Dagger 2,MVC.MVP.MVVM,Jetpack Room
七丶Android车载工程师
涉及:Android Auto,汽车媒体应用,构建Android Auto即时通信应用,构建车载导航和地图注点应用,构建Android Automotive OS视频应用,测试Android车载应用,分发Android汽车应用,适用于汽车的Google Play服务,Android Automotive OS的通知.
八丶Flutter高级工程师
涉及:Dart语法,Flutter动画丶组件丶网络请求以及Flutter3.0简介。
九.Harmony OS
涉及:Ability组件,分布式任务,事件总线,Harmony OS线程,UI自定义控件
十丶Kotlin相关
涉及:对象丶类丶继承丶变量丶常量丶拓展函数等20多个内容****
腾讯T10Android笔记大全(包含(视频+文字):Android基础-性能优化-Framework-compose开源项目-音视频初中高-架构-车载-Flutter-Kotlin-Harmony OS+音视频详细文档。)
私信获取:面试
留言与评论(共有 0 条评论) “” |