LiveData是一个可以在给定生命周期内观察到的数据持有者类。一个观察者可以与一个LifecycleOwner成对地添加,并且只有当配对的LifecycleOwner处于活动状况时,这个观察者才会收到数据变化的奉告。

LiveData-ViewModel-Repository

appreciate下是LiveData结合ViewModel央求数据的伪代码,源码集市这也是JetPack中最常见的一种写法。

ViewMo源码编辑器编程猫下载del层:线程安全继承ViewModel并创立LiveData,经过postValue将数据发射给UI。

class ExViappstoreewModel() : ViewModel() {
private lateinit var repo: ExRepo
val liveData: MutableLiveData<String> = MutableLiveData()
//调用postValue奉告UI数据被改动
fun loadData() = liveData.postValue(repo.loadDataFromRepo())
}

Reposit线程撕裂者ory层:从网络或许数据库中心求数据。数据库办理体系

class ExRepo() {
//网络央求或许从数据库中心求
fun lappleoadDataFromRepo(): String = "网络央求返回的数据"
}

UI层:注册LappreciateiveData的观察者,接收线程和进程的差异是什么数据改动的奉告来更新UI龚俊

class ExFragment: Fragment() {源码码头
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInst数据库体系的中心是anceState数据库体系概论)
val viewModel = V数据库规划iewModelProviders.of(this).get(ExViewModel::class.java)
//注册观察者
viewModel.liveData.observe(this, object:Observer<String> {
override fun onChanged(value: Strinapplicationg) {
//数据库原理央求数据成功后,奉告UI刷新界面
updateUI()
}
})
//央求数据
viewModel线程.loadData()
}
}数据库规划

上面三层基本上便是一个网络央求的闭环,Repository担任从网络或许数据库中心求数据,ViewModel担任调用Repository的数据,并运用LiveData的postValue线程的几种状况()/setValue()办法将数据的更新奉告到UI层,UI则只需求注册一个LiveData的观察者,当所匹数据库体系工程师配的LiveData调用postValue()/setValue()时,就会收到onChange()的奉告,去做更新UI的操作。

【Jetpack篇】LiveData替代EventBus?LiveData的通讯原理和粘性事情刨析

(此图来历网上)

LiveData遵从观察者办法,它的凶appointment猛之处不只在于数据有改动时能及工商银行时奉告UI,并且Li线程池的创立办法有几种veData可以感宫颈癌疫苗知Activity、Fragment等组件的生命周期,随组件毁掉而主动毁掉,不必开发者去操心,极大的减少了内存走漏的或许。

那LiveData是怎样线程池的七个参数通讯并且感知数据库规划组件的生命周期的呢?

LiveData的通讯原理

从上面比方可以知道LiveData的中心首要在于这两步,liveData.observe()以及li线程池面试题veData.postValue(),一个是注册观察者,一个是发送奉告。那么下面的解析就将这两个函数作为切入点。

1.LiveData.observe()

从liveData.o源码编辑器bserve线程撕裂者(宫颈癌)盯梢进去:

LiveData.jAPPava

 private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
new SafeIterableMap数据库体系<>();
......
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NoGonNull ObsAPPerver<? super T> oappearancebserver) {
assertMainThread("observe");
//✅ 榜首部分
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//✅ 第二部分
LifecycleBoundObserver wrapper源码 = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbse线程的几种状况nt(数据库体系工程师observer, wrapp数据库办理体系er);
if (existing != null && !existing.is线程池AttachedTo(owner)) {
throw new IllegalAr数据库查询句子gumentExcept源码码头ion("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
//✅ 第三部分
owner.getLifecy源码集市cle().addObserver(wrapper);
}

observe办法传有两个参数LifecycleOwner和Observer,LifecycleOwner是一个具有Android生命周期的类,一般传入的是Activity和Fragment,Observer是一个接口,内部存在void onCha数据库体系工程师nged(T t)办法。

✅ 榜首部枸杞分: observe内部一开始就存在一个生命周期的appreciate判别,

if (owner.getLifeapprovecycle().getCur源码集市rentState() == DESTROYED) {return;}

当组件生命周数据库有哪几种期现已Destroy了,也就没有必要再持续走下去,则直接return。在这儿,LiveData对生命周期的感知也就慢慢显现出来了。

✅ 第二部分: 首先以LifecycleOwner和Observer作为参数创立了一个LifecycleBoundObserver目标,接着以Observer为key,新创立的LifecycleBoundObserver为value,存储到mObservers这个map中。在后面LiveData postValue中会遍历源码码头出该map的value值ObserverWrapper,Go获取组件生命周期的状况,已此状况来决议分不分发奉告(这部分详情见“第二数据库办理体系末节postValue()”)

那Lifecy线程池cleBoundObserver是什么?

class Li数据库fecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final LifecycleOwner mO数据库体系工程师wner;线程池的创立办法有几种
Lif数据库体系工程师ecycappstoreleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(obse数据库体系rver);
mOwner = owner;
}
.......
}

从源码可以看到,LifecycleBoundObserver继承ObserverWrapper公积金并且完毕了LifecycleEventObserver的接口,LifecycleEventObse数据库有哪几种rver是监听组件生命周期更改并将其分派给接收方的一个接口,而在LifecycleBounGodObserver的结构函数中将observer传给了父类ObsapplicationerverWrapper。LifecycleBo线程是什么意思undObserver其实仅仅包裹着LifecycleOwner和Observe狗狗币r得一个类,其间的完毕有点代理办法的味道。

✅ 第三部分: owner.getLifecycle().addObserver(wra源码集市pper)将新创立的LifecycleBoundObserver添加到Lifecycle中,也便是狗狗币说这个时分观察者注册成功,当LifecycleOwner也便是组件的状况发生改动时,也会奉告到所匹配的observer。

到这儿,UI层view源码网站Model.liveData.observe(this, object:Observer<String> { override f源码本钱un onChanged(value: String) {} })注册观察者的内部解析也就大致清楚了。

2.postValue()

liveData.postValue()是作为一个发射方来奉告数据改appearance动,其内部又做了哪些作业?接下来就一探毕竟。直接从po公积金stValue中最中线程的几种状况心的部分在于将参数value赋值给了一个全局变量源码初公积金借款步:

 protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
pos源码码头tTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.gappreciateetInstance().postToMainThread(mPostValueRunnable);
}

postValue中首先将参数value赋值给了一个全局变量mPendingData,它的初始值为一个空目标,而mPendingData仅仅作为一个中心前言来存储value的值,在后续的操作中会用到,咱们就暂时先记住它。

在毕竟便是一个将线程切换到主线程的操作,首要看mPost源码码头ValueRunnable的完毕:

  private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
pubappearancelic void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
s数据库体系概论etValue((T) newValue);
}
};

在Runnable中,mPendingData赋值给了暂时变量newValue,毕竟调用了setValue()办法。咱们都知道源码编辑器手机版下载LiveData发送奉告可以运用PostValue或许SetValue,而他两的差异就在于,PostValue可以在任意线程中调用,而SetValue只能在主线程中,由于源码集市P数据库ostValue多了一步上面切换主线程的操作。

OK,appearance接下来便是PostValue/SetValue最中心的线程池的创立办法有几种部分。


@MainThread
protected void setVappointmentalue(T val源码集市ue) {
assertMainThread数据库体系概论("setValue");
mVersion++;
mData = value;
dispatchi数据库规划ngValue(n线程是什么意思ull);
}
.源码编辑器手机版下载......
void dispat数据库体系概论chingValue(@线程池Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDis公积金借款patchInvalidated = true;
return;
}
mDispatchi线程池面试题ngValue = true;
do {
mDispatchInvalidated = false;
if数据库体系工程师 (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//✅ 第二部分
for (Iterator<Map.Entry<Observer<? super T>, Observer源码网站Wrapper>> iterator =
mObservers.iteratorWith源码集市Additi源码本钱ons(); iterator.hasNext(); ) {
considerNotify(iterator.next().getVa线程l数据库体系的中心是ue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatching数据库原理Value = false;
}

在setValue中,参数val数据库体系工程师ue将值赋给了一个全局变量mData,而这个mData毕竟将经过mObserver.onChanged((T) mDa线程和进程的差异是什么ta);将需求批改的value值分发给了UI。毕竟调公积金用传入一个null调用dispatchingValue办法。

由于dispatchingValue里的参数为null,也就水到渠成的走到了✅ 第二部分。else一进入便是迭代器在遍历mObservers,而mObservers在榜首末节“1.LiveData.observe()”中说得很清楚,它作为一个map,存储了Obappointmentserver和ObserverWrapper。通数据库规划过遍历,将每个观察者所匹配的ObserverWrapper作为参数传给了cons线程的几种状况iderNotify()办法。

private void considerNotify(ObserverWrapper obsGoerver) {
if (!obs枸杞erver.mActive) {
retappreciateurn;
}
// Check late线程池的创立办法有几种st state b4 dispatch. Maybe it changed state but we didn't get t宫颈癌前期症状he event yet.
//
// we still first check observer.active to keep it as th源码之家e entra源码编辑器编程猫下载nce for events. So even if
// the observer moved数据库规划 to an active state, if we've not received tha数据库原理t event, we better线程的几种状况 not
// notify for a more predic源码码头table notificat数据库体系概论ion order.
if (!obserapplever.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (obse线程池rver.mLastVersion >线程池的七个参数= mVersion) {
return线程池的七个参数;
}
observer源码编辑器编程猫下载.mLastVeappearancersion = mVersion;
observer.mObserver.onChanged((T) mData);
}

而在considerNotify数据库体系工程师()中,先经过observer来宫颈癌疫苗获取组件生命周期的状况,假设处于非活动状况,则回绝建议奉告。在该办法的毕竟, observer.mObserver.onChanged((T) mD源码网站ata),是不是很了解,这便是UI层一开始就完毕的接口,而就在这找到了毕竟的发送方。

小结

LiveData是怎样通讯的?就一句话,UI层注册好一个observer,就存储到一个存储着观察者龚俊的map中,直到开发者调源码编辑器编程猫下载用postValue/s数据库体系工程师etValue则遍历该map,分宣布数据库有哪几种observer的onChan源码网站ged奉告,在此过程中源码编辑器手机版下载,都会监听组件的生命周期,并以此源码网站来判别所匹配的组件是否处于活动状况,不然直接return。

三、LiveData的粘性作业

发送音讯作业早于注册作业线程的生命周期application仍然可以接收到音讯的奉告的为粘性作业

即先调用LiveData的postValue/setValue办法,后注册observe,仍然可以收到onChange()的奉告appearance。从上面的剖析可以知道,LiveData毕竟postValue是将奉告分发给现已注册好的观察者,而LiveData的粘性作业是先发送后注册,那为什么也可以收到奉告呢?是哪里分发了onChange()?

咱们知道粘性作业是注数据库原理册后就收到了奉告google,那么就可以以源码编辑器手机版下载liveData.observe()为切入点,康康源码中的完毕。

 @MainThre源码编辑器手机版下载ad
public void observe(@NonNul源码之家l LifecycleOwner owner, @NonNull Observer&源码编辑器编程猫下载lt;? super T> observe线程撕裂者r) {
......
owner.getLifecycle().addObserver(数据库体系wrapper);
}

LiveData注册观察者,最中心在于owner.getLifecycle().addObserver(wrapper);addObser数据库体系工程师ver是用来添加一个LifecycleObserver,当LifecycleOwner改动状况时,它会被奉告。例如,假设LifecycleOwner处于State#STARTED状况狗狗币,给定的观察者将收到Event#ON_CREATE、Event#ON_START作业。

而咱们盯梢到它的源码年代完毕类里边,源码年代

public class LifecycleR宫颈癌疫苗egistry extends Lifecycle {
......
@Override数据库查询句子
p数据库体系ubl源码本钱ic void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED线程的生命周期;
ObserverWithState stateful线程的几种状况Observer = new Observe源码年代rWithState(observer, initialStat源码编辑器编程猫下载e);
ObserverWithSt源码网站ate previous = mObserverMap.putIfAbsent(observer, stateful源码之家Observer);
if (previous != null) {
return;
}
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
if (lifecycleOwner == null) {
//线程是什么意思 it is null we should be destroyed. Fallback quickly
return;
}
boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent源码编辑器;
State targetState = calcula数据库体系工程师teTargetState(observer);
mAddingObserver数据库Counter++;
while ((statefulObserver.mState.co枸杞mpareTo(targetState) < 0
&& m数据库体系工程师ObserverMap.contains(observer))) {
pushPar数据库体系entStatAPPe(statefulObserver数据库体系的中心是.mState);
✅ 切入点
statefulObserver.dispatchEvent(lifecycleOwner, upEvapproveent(statefulObserver.mState));
popParentState();
// mState / subling may ha数据库体系概论第五版课后答案ve been changed recalculate
targetState = calculateTargetState(observer);
}
......
}
}

LifecycleRegistry继承了Lifecycle,是一个处理多个观察者的类,在这个类中的addObserver办法有一个被我符号✅切入点
statef线程的几种状况ulOapplebserver.源码dispatchEvent(lifecycleOwner, upEvent(statefulObserver.公积金借款mState)),dispatchEvent表明将ON_CREATE、ON_START等作业分发给观察源码编辑器者,以抵达监听生命周期的作用。在dispatchEvent办法中,LifecycleEventObserver经过onStateChanged接口分发给了approve相应的观察者,如下:

 void源码网站 dispatchEvent(LifecycleOwner owner, Event event) {
State newState = getStateAfter(event);
mState = min(mState, newState);
✅ 切入点
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}

看到mLifecycleObserver.onStateChanged(ow宫颈癌疫苗ner,线程池面试题 event)是不是有种了解的感觉,其实在第二节源码剖析中,类LifeappointmentcycleBoundObserver就完毕了LifecycleEventObs线程安全erver枸杞接口,偏狗狗币重写了onStateChanged办法。

class Lifecyc公积金借款leBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
@NonNull
final Li线程池的创立办法有几种fecycleOwner mOwner;
Lifecyc线程安全leBouapp装置下载ndObserver(@NonNull Life数据库体系cycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
,,,,,,
@Overri数据库有哪几种de
public void onStateChanged(LifecycleOwner so数据库体系工程师urce, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState源码网站()狗狗币 == DESTROYED源码) {
remov源码编辑器eObserver(mObserver);
return;
}
✅ 切入点
activeS线程池tateChanged(shouldBeActive());
}
......
}

假设其时生命周期线程池的七个参数状况处于DESTROYED,则将观察者从列表中移除,避免内存走漏,接着就调用了activeStateChanged办法。

void activ源码eStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never源码网站 dispatch anything to inactive
// owner
mActive = n源码编辑器手机版下载ewActive;
bGooole数据库办理体系an wasInactive = LiveData.this.mActiveCoun数据库体系的中心是t == 0;
LiveData.this.mAGoctiveCount += mActive ? 1 : -1;
if (wasInactive &&宫颈癌疫苗amp源码网站; mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInact数据库体系工程师ive();
}
✅ 切入点
if (mActive) {
dispatchingValue(this);
}
}

在 ✅ 切入点之前代码不需求多看,仅仅一些判别当枸杞时活动是否活泼的一起逻辑,中心在于dispatchingValue(this)公积金借款,看到这个办法,线程的生命周期是不是线程池又感觉到一丝了解,假设看了第线程池面试题二节的剖析,就会发现第二节setValue()中也调用了一句dispatchingValue(null),只不过setValue传入的是null,而现在这儿传入了一个this值。接下啦就来看看传如参数和null有什么不同?

void dis线程安全pa龚俊tchingValue(@Nullable ObserverWrappe数据库体系概论r initiator) {
......
do {
mDi源码之家spatchInvalidated = false;
if (initiator != null) {
✅切入点宫颈癌前期症状1
considerNo线程池的七个参数tify(init源码编辑器编程猫下载iator);
initiator = null;
} els源码网站e {
for (Iterator<Map.Entry<Observer<? super T>, Ob龚俊serverWrapper>> iterator =
mObservers.iteratorWithAdd数据库体系概论第五版课后答案itions(); iterator.hasNext(); ) {
considerNotGoify(iterator.next().getValue());
if (mDispatchInvalidat数据库体系概论ed) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}

由于dispatchingValue传入的参数不为null,则逻辑就走进了 ✅切入点1中,接着线程和进程的差异是什么将initiator作为参数,调用了consider狗狗币Notify办法,这个其实和setValue毕竟调用的办法是共同的,只数据库查询句子龚俊传入的参数不同罢了。cons源码之家iderNotify办法中毕竟将数据发送给了观察者源码编辑器手机版下载

  private void considerNotify(ObserverWrapper observer) {
.....源码编辑器手机版下载.
observer.mOb线程池的创立办法有几种server.onChanged((T) mData);
}

到此,整个流程也就梳理完毕。

小结

LiveDat数据库有哪几种a的粘性作业,在于LiveData只要在注册观察者时,就会触发LifecycleOwner的状况改动,并且会将ON_CREATE,ON_START,ON_RESUME三种状况分发给观察者,而这,就触发了onChange的奉告。

【Jetpack篇】LiveData替代EventBus?LiveData的通讯原理和粘性事情刨析