词条信息

admin
admin
超级管理员
词条创建者 发短消息   

相关词条

热门词条

更多>>
什么是端口?到底是做什么的呢?
端口一般指两种,一种是硬件比如路由器或者交换机的插网线的端口,一种是软件的逻辑的概念,比如http的80端口!...
7种进阶方法让你快速测试端口连通性
Ping是Windows、Linux和Unix系统下的一个检查网络连通性的命令工具,对于大部分互联网用户来说很...
电脑开机,总需要按F1,是什么原因造成的?
一.主板掉电这个说法是行业内的叫法了,一般是主板的CMOS电池没电了导致的。也是最常见的一种提示你按F1的提示...
社保降费对个人有什么影响?
下调城镇职工基本养老保险单位缴费比例是政府给企业发的一个大红包,特别是对于企业来说是一个利好,但是对个人来说有...
车辆“出险”对下年保费的影响,到底有多大?
【出险对交强险的影响】【出险对商业险的影响】车辆“出险”对下年保费的影响,到底有多大?这里有必要先提下车险第三...

精选图集

更多>>
简易百科旧版 >>所属分类 >> Android   

Android 架构组件 LiveData 源码分析

标签: Android 架构组件 LiveData 源码分析

顶[0] 发表评论(0) 编辑词条

前言

最近的项目重构中加入LiveData框架,并且小码的T-MVVM也是用了LiveData框架,好不好用你试试就知道(小码口头禅),对于LiveData使用的时候并未做太多的理解,于是乎翻了翻LiveData源代码,在此做下笔记。

什么是LiveData

LiveData是一个数据持有类。它具有以下特点:

  • 数据可以被观察者订阅;
  • 能够感知组件(Fragment、Activity、Service)的生命周期;
  • 只有在组件出于激活状态才会通知观察者有数据更新;

LiveData能为我们做什么

  • 能够保证数据和UI统一,LiveData采用了观察者模式,LiveData是被观察者,当数据有变化时会通知UI。
  • 减少内存泄漏,LiveData能够感知到组件的生命周期,当组件处于DESTROYED状态时,观察者对象会被清除,当Activity停止时不会导致Crash,因为组件处于非激活状态时,不会收到LiveData中数据变化的通知。
  • 不需要额外的手动处理来响应生命周期的变化,因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。
  • 组件和数据相关的内容能实时更新,组件在前台的时候能够实时收到数据改变的通知,当组件从后台到前台来时,LiveData能够将最新的数据通知组件,因此保证了组件中和数据相关的内容能够实时更新。 若果横竖屏切换(configuration change)时,不需要额外的处理来保存数据,当屏幕方向变化时,组件会被recreate,然而系统并不能保证你的数据能够被恢复的。当我们采用LiveData保存数据时,因为数据和组件分离了。当组件被recreate,数据还是存在LiveData中,并不会被销毁。
  • 资源共享。

从使用分析

  • 使用LiveData对象,
  • 继承LiveData类,如MutableLiveData, 发起数据通知2种方式:postValue和setValue:

privateMutableLiveData<String> mData= newMutableLiveData();

mBookData.postValue( "Hello LiveData");

// mBookData.setValue("Hello LiveData");

此处postValue和setValue的区别,下文会提

注册观察者并监听数据变化:

mData.observe( thisnewObserver< String>() {

@Override

public voidonChanged( @NullableStringstr) {

Toast.makeText( this, str, Toast.LENGTH_SHORT).show();

}

});

使用非常简单,仅此而已

通过observe方法注册观察者,哪咋们就看看observe里面具体干了什么,源代码165行走起,

//注册观察

@MainThread

publicvoidobserve(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer){

if(owner.getLifecycle().getCurrentState() == DESTROYED) {

// ignore

return;

}

LifecycleBoundObserver wrapper = newLifecycleBoundObserver(owner, observer);

ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

if(existing != null&& !existing.isAttachedTo(owner)) {

thrownewIllegalArgumentException( "Cannot add the same observer"

" with different lifecycles");

}

if(existing != null) {

return;

}

owner.getLifecycle().addObserver(wrapper);

}

observe方法接收2个参数,一个是具有生命周期的LifecycleOwner,另一个是观察者Observer ,首先判断LifecycleOwner当前的生命周期是否为Destroyed,如果是则直接 return;如果不等于Destroyed,接下来往下看, 此处new了一个内部类LifecycleBoundObserver对象并且构造方法传入了具有生命周期的LifecycleOwner和观察者,这是个什么鬼,看看他的具体方法,LifecycleBoundObserver继承自ObserverWrapper,并实现GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。由此可以看出LifecycleBoundObserver类就是把Observer和生命周期关联起来,ok,那我们先看看LifecycleBoundObserver方法,源代码349行走起,

classLifecycleBoundObserverextendsObserverWrapperimplementsGenericLifecycleObserver{

@NonNullfinalLifecycleOwner mOwner;

LifecycleBoundObserver( @NonNullLifecycleOwner owner, Observer<T> observer) {

super(observer);

mOwner = owner;

}

@Override

booleanshouldBeActive(){

returnmOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);

}

@Override

publicvoidonStateChanged(LifecycleOwner source, Lifecycle.Event event){

if(mOwner.getLifecycle().getCurrentState() == DESTROYED) {

removeObserver(mObserver);

return;

}

activeStateChanged(shouldBeActive());

}

@Override

booleanisAttachedTo(LifecycleOwner owner){

returnmOwner == owner;

}

@Override

voiddetachObserver(){

mOwner.getLifecycle().removeObserver( this);

}

}

此方法中,我们先看onStateChanged()方法,当生命周期变化时会回调,如果getCurrentState() == DESTROYED则removeObserver,反之则调用父类ObserverWrapper的activeStateChanged()方法,源代码382行走起,

privateabstractclassObserverWrapper{

finalObserver<T> mObserver;

booleanmActive;

intmLastVersion = START_VERSION;

ObserverWrapper(Observer<T> observer) {

mObserver = observer;

}

abstractbooleanshouldBeActive();

booleanisAttachedTo(LifecycleOwner owner){

returnfalse;

}

voiddetachObserver(){

}

voidactiveStateChanged(booleannewActive){

if(newActive == mActive) {

return;

}

// immediately set active state, so we'd never dispatch anything to inactive

// owner

mActive = newActive;

booleanwasInactive = 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);

}

}

}

activeStateChanged()是干嘛的,首先判断activeState新旧状态是否相同,不同则把新的状态赋给mActive,是生命周期状态处于ACTIVE情况下的逻辑处理。如果新的状态和旧的状态相同则直接返回。这里有个常量LiveData.this.mActiveCount,看注释可以理解为观察者处于活动状态

个数,往下看 if (wasInactive && mActive)如果mActiveCount=0并且mActive为true,即观察者处于活动状态

个数从0变为1个则调用onActive(); 观察者处于活动状态

个数从1变为0时则调用onInactive()。然而onActive(),onInactive()并没有任何实现代码。好了,接下来继续往下看dispatchingValue(this);应该就是数据变化消息调度。源代码112行走起,

private voiddispatchingValue( @NullableObserverWrapper initiator) {

if(mDispatchingValue) {

mDispatchInvalidated = true;

return;

}

mDispatchingValue = true;

do{

mDispatchInvalidated = false;

if(initiator != null) {

considerNotify(initiator);

initiator = null;

else{

forIteratorMap.Entry<Observer<T>, ObserverWrapper>> iterator =

mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

considerNotify(iterator.next().getValue());

if(mDispatchInvalidated) {

break;

}

}

}

while(mDispatchInvalidated);

mDispatchingValue = false;

}

前面的几行if 判断姑且先不看,先看从if(initiator != null)开始看,如果initiator!= null调用considerNotify(initiator)方法;源代码91行走起,

privatevoid 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.mObserver.onChanged((T) mData); Observer的数据变化回调;好了我们再回过头看看initiator == null的逻辑,

forIteratorMap.Entry<Observer<T>, ObserverWrapper>> iterator =

mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

considerNotify(iterator.next().getValue());

if(mDispatchInvalidated) {

break;

}

}

如果initiator == null 则会通过迭代器mObservers遍历获取ObserverWrapper,最终还是调用considerNotify方法;既然有取ObserverWrapper,咋们再看看在哪儿存的,在源码171行:

ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);

if(existing != null&& !existing.isAttachedTo(owner)) {

thrownewIllegalArgumentException( "Cannot add the same observer"

" with different lifecycles");

}

if(existing != null) {

return;

}

owner.getLifecycle().addObserver(wrapper);

mObservers.putIfAbsent(observer, wrapper)存入容器中,mObservers.putIfAbsent这个添加数据的方式貌似很少见,于是乎在看看mObservers是个什么数据容器,成员变量中:

privateSafeIterableMap<Observer<T>, ObserverWrapper> mObservers =

newSafeIterableMap<>();

这是个什么鬼,貌似以前很少见,查阅资料发现:

SafeIterableMap有以下特性:

1.支持键值对存储,用链表实现,模拟成Map的接口

2.支持在遍历的过程中删除任意元素,不会触发ConcurrentModifiedException

3.非线程安全

感兴趣的可自行查阅,此处不再详细介绍,

最后addObserver添加注册。

下面在看看数据发起通知的逻辑,数据发起通知有2中方式:

publicclassMutableLiveData<TextendsLiveData<T{

@Override

publicvoidpostValue(T value){

super.postValue(value);

}

@Override

publicvoidsetValue(T value){

super.setValue(value);

}

}

setValue和postValue2中方式,我们先看看setValue代码:

MainThread

protectedvoidsetValue(value) {

assertMainThread( "setValue");

mVersion++;

mData = value;

dispatchingValue( null);

}

privatestaticvoidassertMainThread(String methodName{

if(!ArchTaskExecutor.getInstance().isMainThread()) {

thrownewIllegalStateException( "Cannot invoke "+ methodName + " on a background"

" thread");

}

}

setValue第一行代码 assertMainThread("setValue");则是判断是否在主线程,所以貌似setValue方式必须在主线程中执行,如果非主线程则抛出异常。

再看看postValue:

protectedvoidpostValue(value{

boolean postTask;

synchronized (mDataLock) {

postTask = mPendingData == NOT_SET;

mPendingData = value;

}

if(!postTask) {

return;

}

ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);

}

则postValue调用postToMainThread方法,最终还是用过setValue方式:

privatefinalRunnable mPostValueRunnable = newRunnable() {

@Override

publicvoidrun(){

Object newValue;

synchronized(mDataLock) {

newValue = mPendingData;

mPendingData = NOT_SET;

}

//noinspection unchecked

setValue((T) newValue);

}

};

因此最终明白为什么setValue方法只能在主线程中调用,postValue可以在任何线程中调用,如果是在后台子线程中更新LiveData的值,必须调用postValue。

至此大概明白了LiveData是干嘛的 ,怎么干的,总的来说还是很好用的,于是乎就有个小小的想法,平时用Eventbus,RxBus什么的,貌似感觉LiveData也可以实现事件总线,既然有了想法,那就干呗,

/**

* 事件总线

*

* @author:tqzhang on 18/9/11 17:22

*/

publicclassLiveBus{

privatestaticvolatileLiveBus instance;

privatefinal Map<Object, MutableLiveData<Object>> mLiveBus;

privateLiveBus() {

mLiveBus = newHashMap<>();

}

publicstaticLiveBus getDefault() {

if(instance == null) {

synchronized (LiveBus.class) {

if(instance == null) {

instance = newLiveBus();

}

}

}

returninstance;

}

/**

*

* subscriber 注册时间 key

*/

public<T> MutableLiveData<T> subscribe(Object subscriber, Class<T> tMutableLiveData{

checkNotNull(subscriber);

checkNotNull(tMutableLiveData);

if(!mLiveBus.containsKey(subscriber)) {

mLiveBus.put(subscriber, newMutableLiveData<>());

}

return(MutableLiveData<T>) mLiveBus. get(subscriber);

}

}

简单的50行代码实现类似Eventbus,RxBus的功能,小码亲测了,挺好使的。

//发起通知

LiveBus.getDefault().subscribe( "livedata"Stringclass).postValue( "hello LiveData");

//注册观察

LiveBus.getDefault().subscribe( "livedata"Stringclass).observe( thisnewObserver< String>() {

@Override

public voidonChanged( @NullableStrings) {

Toast.makeText(activity, s, Toast.LENGTH_SHORT).show();

}

});


 

 

附件列表


按字母顺序浏览:A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

→我们致力于为广大网民解决所遇到的各种电脑技术问题
 如果您认为本词条还有待完善,请 编辑词条

上一篇Android 如何保存与恢复自定义View的状态?
下一篇8 大主流自媒体平台优缺点以及运营建议

0
1. 本站部分内容来自互联网,如有任何版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
2. 本站内容仅供参考,如果您需要解决具体问题,建议您咨询相关领域专业人士。
3. 如果您没有找到需要的百科词条,您可以到百科问答提问或创建词条,等待高手解答。

关于本词条的提问

查看全部/我要提问>>