浅析ViewModel、LiveData、DataBinding原理

一.ViewModel
在MVVM模式中,数据和业务逻辑可以集中在ViewModel中处理,实现功能时只需要在ViewModel中关注数据和业务即可,不需要和UI或者控件打交道。
1.ViewModel的创建和复用流程如下

ViewModel复用基本原理
ViewModel复用基本原理

2.销毁
在ViewModelStore类中找到了clear(),也就是清除了缓存。
1
2
3
4
5
6
public final void clear() {
for (ViewModel vm : mMap.values()) {
vm.onCleared();
}
mMap.clear();
}

Activity中的销毁:使用LifeCycle监听生命周期,最后在ON_DESTROY中清除store:getViewModelStore().clear();
Fragment中的销毁:
首先需要明确,在fragment中有几个状态:

1
2
3
4
5
6
7
8
9
static final int INITIALIZING = -1;          // Not yet attached.
static final int ATTACHED = 0; // Attached to the host.
static final int CREATED = 1; // Created.
static final int VIEW_CREATED = 2; // View Created.
static final int AWAITING_EXIT_EFFECTS = 3; // Downward state, awaiting exit effects
static final int ACTIVITY_CREATED = 4; // Fully created, not started.
static final int STARTED = 5; // Created and started, not resumed.
static final int AWAITING_ENTER_EFFECTS = 6; // Upward state, awaiting enter effects
static final int RESUMED = 7; // Created started and resumed.

在add时,状态是从INITIALIZING一步步升级到RESUMED
相反,remove的时候,状态则会从RESUMED一步步退回到INITIALIZING,具体可以参考下面的图片:图片来源:https://www.sohu.com/a/471240132_121124376

Fragment生命周期和状态转移关系图
Fragment生命周期和状态转移关系图

再回到刚刚的ViewModelStore的clear,点击查看调用路径:
FragmentManagerViewModel::clearNonConfigState <- FragmentStateManager::destroy()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void moveToExpectedState() {
int newState;
// 计算新状态
while ((newState = computeExpectedState()) != mFragment.mState) {
if (newState > mFragment.mState) {
// 新状态大于当前状态,说明是状态升级
……
} else {
// 状态降级,说明此时是销毁
int nextStep = mFragment.mState - 1;
switch (nextStep) {
case Fragment.ATTACHED:
destroy();
break;
}
}
}
……
}


void moveToState(@NonNull Fragment f, int newState) {
if (f.mState <= newState) {
// 状态升级
……
} else if (f.mState > newState) {
// 状态降级
switch (f.mState) {
// fall through
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mExitAnimationCancellationSignals.get(f) != null) {
// We are waiting for the fragment's view to finish animating away.
newState = Fragment.CREATED;
} else {
// 销毁
fragmentStateManager.destroy();
}
}

}
}
}

这时会看到,只有当状态退回到CREATE和ATTACHED时,才会调用destroy,说明此时这个fragment正在销毁,也可以看到调用完clearNonConfigState,会调用fragment.onDestroy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void destroy() {
boolean beingRemoved = mFragment.mRemoving && !mFragment.isInBackStack();
boolean shouldDestroy = beingRemoved
|| mFragmentStore.getNonConfig().shouldDestroy(mFragment);
if (shouldDestroy) {
……
if (beingRemoved || shouldClear) {
// 在这里调用清除方法
mFragmentStore.getNonConfig().clearNonConfigState(mFragment);
}
// 最后会走到fragment.onDestroy
mFragment.performDestroy();
……
}

二、LiveData
基本原理:LiveData是感应数据的变化。首先对某个变量设置observer,当调用setValue或postValue时,会找到对应的observer并回调到onChanged方法。
源码大致解析如下图:

LiveData基本原理
LiveData基本原理

三、databinding
databinding:数据绑定,是Google官方发布的一个框架,是mvvm在android上的一种实现,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰,可以直接绑定数据到xml中,并实现自动刷新。databinding能够省去findviewbyId,大量减少activity的代码,数据能够单向或双向绑定到layout文件中,有助于防止内存泄漏,而且能自动进行空检测以避免空指针异常。

databinding包括单向数据传递和双向传递
单向传递主要原理是通过setXX来改变所有数据(如viewModel或者user这样具体的对象),通过requestRebind进行全部更新绘制
双向传递则是利用textWatcher的原理,当监听到文字变化时,改变对象的某个属性。由于初始化是一定会调用setXX来绑定数据和view,此时会添加一个callback。当对象属性(如user.setName())改变时会notify对应的callback,表示数据改变。最后也是通过requestRebind更新
大致原理图如下:

databinding基本原理
databinding基本原理

以上是jetpack这几个组件的原理。图是自己根据源码大概画的流程,如有哪里错误或者需要解释的可以留下评论。当然如果有幸能得到认可,想要转发的话,也请标注一下来源,谢谢。