基于Google架构组件的MVVM实现
1. mvvm简介
1.1 概述
现在MVP架构在应用开发中普遍使用,但是随着业务的增加,其暴露的缺点也越来越明显,总结起来有以下几点:
- 随着业务的增加,接口暴增,代码成倍增长,所有交互都需要通过接口传递信息,对开发者造成困扰;
- Presenter作为UI和Model层的桥梁,造成Presenter臃肿,维护困难;
- Presenter中持有View的引用,Presenter设计不健壮会存在内存泄露的风险。
在项目开发中,使用MVC、MVP及MVVM并没有严格的限定,视项目业务量来定,优秀的架构能让软件高内聚、低耦合、可维护、可扩展,其实,对于MVP或者MVVM没有绝对好坏,MVP->MVVM只不过让模型和视图分离得更加的彻底,解决一部分MVP存在的缺点,但是,并不是说MVVM完美无缺,MVVM也存在一定的缺陷,后面我们会讲到。
在此之前,我们提到MVVM架构,基于DataBinding, 但是存在以下缺点:
- 数据绑定增加Bug调试难度;
- 复杂的页面,model也会很大,虽然使用方便了也很容易保证了数据的一致性,当长期持有,不利于释放内存;
- 数据双向绑定不利于View重用。
1.2 Jetpack组件简介
鉴于以上问题,采用Google架构组件搭建一个MVVM的架构, 该架构中使用组件包括ViewModel、LiveData、Lifecycles、Retrofit、OkHttp和Rxjava泛型限定,深度解耦。其中LiveData及ViewModel是Android Jetpack中的一部分, Android Jetpack是Google在2018.5月的IO大会上发布,它是新一代组件、工具和架构指导,旨在加快开发者的 Android 应用开发速度。Android Jetpack 组件将现有的支持库与架构组件联系起来, Jetpack 组件以“未捆绑的”库形式提供,这些库不是基础 Android 平台的一部分。这就意味着,我们可以根据自己的需求采用每一个组件。
对于Jetpack想有更详细的了解,可以参考官网
https://developer.android.com/jetpack/
1.3 ViewModel、LiveData及Lifecycles
生命周期感知的能力主要主要依赖于以下组件ViewModel、LiveData及LifeCycles
1.3.1 ViewModel
ViewModel类被设计为通过lifecycle感知的方式存储和管理UI相关数据。ViewModel类允许数据在配置更改(如屏幕旋转)中保活。
Android框架管理着Activity/Fragment的生命周期,决定了Activity/Fragment销毁或重建,以响应某些完全超出您控制的用户操作或设备事件。
如果系统Android框架销毁或者重建了Activity/Fragment,则在其中存储的任何与UI相关的临时数据都会丢失。例如,您的应用程序可能在一个Activity中包含用户的列表。当配置更改时候activity会重新创建,新Activity必须重新获取用户列表。对于简单数据,该Activity可以使用onSaveInstanceState()方法并从onCreate()中的bundle恢复其数据,但是这种方法仅适用于可以序列化/反序列化的少量数据,而不适用于潜在的大量数据,如用户列表或位图。
另一个问题是Activity/Fragment经常需要进行异步调用,这可能需要一些时间才能返回。Activity/Fragment需要管理这些调用,并确保在自己销毁的时候,系统能清理它们,以避免潜在的内存泄漏。这种管理需要大量的维护,在配置更改时需要重新创建对象的情况下,这是资源的浪费,因为对象可能必须重新发出它已经发出的调用。
Activity/Fragment主要用于显示UI数据、对用户动作作出反应或处理与操作系统间的通信(如权限请求)。要求Activity/Fragment还负责从数据库或网络加载数据,这些都造成了Activity/Fragment代码急剧膨胀。将过多的职责分配给Activity/Fragment会导致一个类试图自己处理应用程序的所有工作,而不是将工作委托给其他类。以这种方式给Activity/Fragment分配过度的职责也会使测试变得更加困难。
ViewModel优点:
- 同步关联生命周期
- 数据共享
- 复用性强
1.3.2 LiveData
LiveData是一个observable数据持有类。与常规observable不同,LiveData是生命周期感知的,这意味着它跟随其他应用程序组件(如activities, fragments, or services)的生命周期。这种感知能力确保LiveData只更新处于活跃生命周期状态的应用程序组件。
LiveData与一个Observer关联,如果观察者的生命周期处于STARTED或RESUMED状态,则表示观察者处于活动状态。LiveData只通知活跃的观察者做更新。注册到LiveData对象中的不活跃的观察者则得不到数据更新的通知。
您可以注册一个observer并与实现了LifecycleOwner接口的对象配对。这种关系允许当相应的Lifecycle对象的状态改变为DESTROYED时,观察者被移除。这对于activities and fragments尤其有用,因为它们可以安全地观察LiveData对象,而不用担心泄漏——当activities 和 fragments的生命周期被销毁时,它们会立即取消订阅。
LiveData优点:
- 确保UI界面的数据状态
- 没有内存泄漏,不会因为Activity的不可见导致Crash
- 不用再人为的处理生命周期
- 共享资源
1.3.3 LifeCycles
LifeCycles感知组件响应于另一组件的生命周期状态(如Activity和Fragment)的变化而执行动作。这些组件有助于产生更好的组织性和更轻量级的代码,这更易于维护。
一种常见的模式是在Activity和Fragment的生命周期方法中实现依赖组件的动作。然而,这种模式导致代码的组织和错误扩散。通过使用生命周期感知组件,可以将依赖组件的代码从生命周期方法中移入组件本身。
Lifecycles是生命周期管理组件,support 26 以上的兼容包中的AppCompatActivity与Fragment中默认已实现了LifeCycleOwner接口,保证了LiveData及ViewModel具备了生命周期感知与内存缓存的能力。
1.4 基于架构组件的MVVM
MVVM的调用和MVP类似,在MVP中全部由Presenter负责ViewModel之间的数据同步,而MVVM中ViewModel充当了Presenter的角色,ViewModel是View与Model的连接器,持有可被观察的数据持有者和网络请求操作,数据变更实时渲染UI。
基于架构组件的MVVM架构图
数据库操作可以采用Google官方的Room组件, 提供注解操作数据库的API,极大简化了数据库操作的过程,另外提供了数据库升级、迁移及Provider操作支持。
需要了解更多关于Room的使用,可以参考官方指南:
https://developer.android.com/training/data-storage/room/
网络操作这里采用OkHttp3+Retrofit,异步框架采用RxJava。
2. 基于架构组件的MVVM实现
下面的内容会讲述MVVM的代码实现
2.1 搭建基于架构组件的MVVM框架
- 先定义AbsViewModel基类
public class AbsViewModel<T extends AbsRepository> extends AndroidViewModel {
public T mRepository;
public AbsViewModel(@NonNull Application application) {
super(application);
mRepository = TUtil.getNewInstance(this, 0);
}
@Override
protected void onCleared() {
super.onCleared();
if (mRepository != null) {
mRepository.unDisposable();
}
}
}
AbsViewModel通过泛型类型参数AbsRepository子类初始化Repository数据仓库,同时在activity/fragment走onDestroy()生命周期方法时 AbsViewModel回调onCleared,即页面销毁是用来取消网络请求或资源释放等操作。
开发中不建议直接通过ViewModel获取网络数据,这里我们将工作交给一个新的模块Repository。Repository只负责数据处理,提供干净的api,同时方便切换数据来源。
- 定义AbsRepository
public abstract class AbsRepository {
private CompositeDisposable mCompositeDisposable;
public AbsRepository() {
}
protected void addDisposable(Disposable disposable) {
if (mCompositeDisposable == null) {
mCompositeDisposable = new CompositeDisposable();
}
mCompositeDisposable.add(disposable);
}
public void unDisposable() {
if (mCompositeDisposable != null && mCompositeDisposable.isDisposed()) {
mCompositeDisposable.clear();
}
}
}
AbsRepository主要是获取ApiService和网络请求订阅容器,方便管理网络请求,即页面销毁是取消网络请求操作。
- 定义AbsLifecycleActivity
AbsLifecycleActivity基类继承BaseActivity,BaseActivity中主要是定义一些与初始化和Adapter绑定相关的模板方法,便于子类去实现与复写。然后自定义AbsLifecycleActivity基类继承BaseActivity,BaseActivity中主要是定义一些与初始化和Adapter绑定相关的模板方法,便于子类去实现与复写。
abstract public class AbsLifecycleActivity<T extends AbsViewModel> extends BaseActivity
implements IBaseView, BaseViewInterface {
private static final String TAG = AbsLifecycleActivity.class.getSimpleName();
protected T mViewModel;
protected Context mContext;
protected AbsLifecycleActivity abstractActivity;
protected LayoutInflater mInflater;
protected Object mStateEventKey;
protected String mStateEventTag;
protected Observer observer = new Observer<String>() {
@Override
public void onChanged(@Nullable String state) {
if (!TextUtils.isEmpty(state)) {
if (StateConstants.ERROR_STATE.equals(state)) {
showError(StateConstants.ERROR_STATE);
} else if (StateConstants.NET_WORK_STATE.equals(state)) {
showError(StateConstants.NET_WORK_STATE);
} else if (StateConstants.LOADING_STATE.equals(state)) {
showLoading();
} else if (StateConstants.SUCCESS_STATE.equals(state)) {
showSuccess();
}
}
}
};
private List<Object> eventKeys = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
onBeforeSetContentLayout();
if (getLayoutId() != 0) {
setContentView(getLayoutId());
}
mInflater = getLayoutInflater();
init(savedInstanceState);
initView();
initData();
}
protected abstract int getLayoutId();
protected void init(Bundle savedInstanceState) {
Logger.d(TAG, "init savedInstanceState");
mViewModel = VMProviders(this, (Class<T>) TUtil.getInstance(this, 0));
if (null != mViewModel) {
dataObserver();
mStateEventKey = getStateEventKey();
mStateEventTag = getStateEventTag();
eventKeys.add(new StringBuilder((String) mStateEventKey).append(mStateEventTag).toString());
LiveBus.getDefault().subscribe(mStateEventKey, mStateEventTag).observe(this, observer);
}
}
.........................
.........................
/**
* DataState tag
*
* @return
*/
protected String getStateEventTag() {
return "";
}
/**
* get Data event key
*
* @return
*/
protected Object getStateEventKey() {
return "";
}
protected <T extends ViewModel> T VMProviders(FragmentActivity fragment, @NonNull Class modelClass) {
return (T) ViewModelProviders.of(fragment).get(modelClass);
}
protected void dataObserver() {
}
protected <T> MutableLiveData<T> registerObserver(Object eventKey, Class<T> tClass) {
return registerObserver(eventKey, null, tClass);
}
protected <T> MutableLiveData<T> registerObserver(Object eventKey, String tag, Class<T> tClass) {
String event;
if (TextUtils.isEmpty(tag)) {
event = (String) eventKey;
} else {
event = eventKey + tag;
}
eventKeys.add(event);
return LiveBus.getDefault().subscribe(eventKey, tag, tClass);
}
protected void onBeforeSetContentLayout() {
mContext = getApplicationContext();
abstractActivity = this;
ActivityTaskManager.INSTANCE.pushActivity(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityTaskManager.INSTANCE.removeActivity(this);
//从数据总线中删除该界面所订阅的数据
if (eventKeys != null && eventKeys.size() > 0) {
for (int i = 0; i < eventKeys.size(); i++) {
LiveBus.getDefault().clear(eventKeys.get(i));
}
}
}
}
在init()方法中通过AbsViewModel子类泛型类型参数获取Class,在通过ViewModelProviders.of(fragment).get(modelClass))实例化ViewModel,到此我们的基类基本编写完毕。
如果界面采用Fragment实现,定义AbsLifeCycleFragment步骤与上面类似。
注意:
这里的AbsLifeCycleFragment及AbsLifecycleActivity最终必须继承自 support API 26以上的android.support.v4.app.Fragment
与android.support.v4.app.FragmentActivity
, 因为这两个类默认已经实现了LifeCycles组件接口,所以其承载的LiveData及ViewModel具备了生命周期感知能力,具体实现后面会讲到。
2.2 MVVM使用实例
下面以获取会议列表的业务来演示下该MVVM框架的使用, 步骤如下:
- 实现获取会议列表的ConfListActivity类
public class ConfListActivity extends AbsLifecycleActivity<ConfListViewModel> {
private ListView mConfListView;
@Override
protected Object getStateEventKey() {
return Constants.EVENT_KEY_QUERY_CONF_LIST_STATE;
}
..................................
..................................
@Override
public void initData() {
mViewModel.queryConfList(mContext, Constants.DEFAULT_PAGE_NO, Constants.DEFAULT_PAGE_ITEMS);
}
..................................
..................................
@Override
protected void dataObserver() {
registerObserver(Constants.EVENT_KEY_QUERY_CONF_LIST, ConfListVo.class).observe(this,
new Observer<ConfListVo>() {
@Override
public void onChanged(@Nullable ConfListVo confListVo) {
if(confListVo != null){
QueryListResult result = confListVo.queryListResult;
if(result != null){
Log.d(TAG,"has Conf summary result.");
showConferenceList(result.getSqSummaryList());
}
}
}
});
}
..................................
..................................
- 实现获取会议列表的ConfListViewModel类
public class ConfListViewModel extends AbsViewModel<ConfCtrRepository> {
public ConfListViewModel(Application application){
super(application);
}
public void queryConfList(Context context, int pageNum, int pageSize){
Account account = AccountDbHelper.getAccount(context);
QueryListRequest request = new QueryListRequest()
.setStrUserId(account.getUserId())
.setEnQryType(QueryListRequest.SELF)
.setQueryType(QueryListRequest.FOR_MEMBER)
.setlPageNo(pageNum)
.setlPageItemsNo(pageSize);
mRepository.queryConfList(request, null);
}
public void queryConfInfo(Context context,String confId){
Account account = AccountDbHelper.getAccount(context);
QueryInfoRequest request = new QueryInfoRequest()
.setStrUserId(account.getUserId())
.setStrConfID(confId)
.setiCycleNo(0);
mRepository.queryConf(request, null);
}
}
- 实现获取会议列表的ConfCtrRepository类
public class ConfCtrRepository extends BaseRepository {
//1. interface query ConfList
public void queryConfList(QueryListRequest confListRb, final ITaskCallback callback){
RequestBody requestBody = buildRequestBody(confListRb);
addDisposable(apiService.queryConferenceList(requestBody)
.compose(RxSchedulers.<QueryListResult>io_main())
.subscribeWith(new RxSubscriber<QueryListResult>(){
@Override
protected void onNoNetWork() {
showPageState(Constants.EVENT_KEY_QUERY_CONF_LIST_STATE, StateConstants.NET_WORK_STATE);
}
@Override
public void onSuccess(QueryListResult result) {
if(result == null){
showPageState(Constants.EVENT_KEY_QUERY_CONF_LIST_STATE, StateConstants.ERROR_STATE);
}else{
int resultCode = result.getIResult();
if(resultCode == 0){
sendData(Constants.EVENT_KEY_QUERY_CONF_LIST, new ConfListVo().setQueryListResult(result));
showPageState(Constants.EVENT_KEY_QUERY_CONF_LIST_STATE, StateConstants.SUCCESS_STATE);
try {
if(callback != null){
callback.onSuccess(new Result<QueryListResult>(result));
}
} catch (RemoteException e) {
e.printStackTrace();
}
}else{
showPageState(Constants.EVENT_KEY_QUERY_CONF_LIST_STATE, StateConstants.ERROR_STATE);
try {
if(callback != null){
callback.onError(resultCode);
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onFailure(String msg) {
showPageState(Constants.EVENT_KEY_QUERY_CONF_LIST_STATE, StateConstants.ERROR_STATE);
try {
if(callback != null){
callback.onFailed();
}
} catch (RemoteException e) {
e.printStackTrace();
}
}
}));
}
......................................................
......................................................
}
至此,实现会议列表加载的MVVM框架实现就完成了。
下图展示了MVVM架构实现
MVVM架构实现
下图展示了MVVM架构App包结构
MVVM架构App包结构
3. 生命周期感知原理
3.1 源码分析
Support 26以上的兼容包中的Fragment及FragmentActivity默认已实现了LifeCycle组件的接口,所以继承自这两则的子类也就具备了生命周期感知的能力。Support包中Activity继承关系如下:
public class SupportActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
..............................
..............................
@Override
@SuppressWarnings("RestrictedApi")
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//具备生命周期感知的关键
ReportFragment.injectIfNeededIn(this);
}
..............................
..............................
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
..............................
..............................
}
在onCreate中注入了一个ReportFragment类,这个是生命周期感知的关键,生命周期Event的分发就是在ReportFragment中完成。它是通过FragmentManager将自己注入到Activity中,我们知道Fragment的生命周期是嵌入到Activity的生命周期中的,所以会与Activity周期保持一致。所以,在Activity执行生命周期回调的时候,ReportFragment也会触发生命周期回调,进而通过dispatch()方法分发生命周期事件。
public class ReportFragment extends Fragment {
private static final String REPORT_FRAGMENT_TAG = "android.arch.lifecycle"
+ ".LifecycleDispatcher.report_fragment_tag";
public static void injectIfNeededIn(Activity activity) {
// ProcessLifecycleOwner should always correctly work and some activities may not extend
// FragmentActivity from support lib, so we use framework fragments for activities
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
// Hopefully, we are the first to make a transaction.
manager.executePendingTransactions();
}
}
static ReportFragment get(Activity activity) {
return (ReportFragment) activity.getFragmentManager().findFragmentByTag(
REPORT_FRAGMENT_TAG);
}
private ActivityInitializationListener mProcessListener;
private void dispatchCreate(ActivityInitializationListener listener) {
if (listener != null) {
listener.onCreate();
}
}
private void dispatchStart(ActivityInitializationListener listener) {
if (listener != null) {
listener.onStart();
}
}
private void dispatchResume(ActivityInitializationListener listener) {
if (listener != null) {
listener.onResume();
}
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
dispatchCreate(mProcessListener);
dispatch(Lifecycle.Event.ON_CREATE);
}
@Override
public void onStart() {
super.onStart();
dispatchStart(mProcessListener);
dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume() {
super.onResume();
dispatchResume(mProcessListener);
dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause() {
super.onPause();
dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onStop() {
super.onStop();
dispatch(Lifecycle.Event.ON_STOP);
}
@Override
public void onDestroy() {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
// just want to be sure that we won't leak reference to an activity
mProcessListener = null;
}
private void dispatch(Lifecycle.Event event) {
Activity activity = getActivity();
if (activity instanceof LifecycleRegistryOwner) {
((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
return;
}
if (activity instanceof LifecycleOwner) {
Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
}
void setProcessListener(ActivityInitializationListener processListener) {
mProcessListener = processListener;
}
interface ActivityInitializationListener {
void onCreate();
void onStart();
void onResume();
}
}
在ReportFragment中,我们看到dispatch(Lifecycle.Event event)
方法中会涉及LifecycleOwner与LifecycleRegistry, LifecycleRegistry实现了LifeCycleEvent的处理, 而LifecycleOwner是一个接口被SupportActivity实现。那么这些生命周期事件是如何被处理的呢?
前面我们讲过LiveData具备了生命周期感知能力,那么我们就来分析下LiveData是如何实现的。
下面我们继续跟进dispatch(Lifecycle.Event event)
方法,在该方法中,LifeCycleEvent最终被LifecycleRegistry类中的handleLifecycleEvent()
函数处理,下面是LifecycleRegistry类代码的实现,该类实现了Lifecycle抽象类。
/**
* An implementation of {@link Lifecycle} that can handle multiple observers.
* <p>
* It is used by Fragments and Support Library Activities. You can also directly use it if you have
* a custom LifecycleOwner.
*/
public class LifecycleRegistry extends Lifecycle {
private static final String LOG_TAG = "LifecycleRegistry";
/**
* Custom list that keeps observers and can handle removals / additions during traversal.
*
* Invariant: at any moment of time for observer1 & observer2:
* if addition_order(observer1) < addition_order(observer2), then
* state(observer1) >= state(observer2),
*/
private FastSafeIterableMap<LifecycleObserver, ObserverWithState> mObserverMap =
new FastSafeIterableMap<>();
/**
* Current state
*/
private State mState;
/**
* The provider that owns this Lifecycle.
* Only WeakReference on LifecycleOwner is kept, so if somebody leaks Lifecycle, they won't leak
* the whole Fragment / Activity. However, to leak Lifecycle object isn't great idea neither,
* because it keeps strong references on all other listeners, so you'll leak all of them as
* well.
*/
private final WeakReference<LifecycleOwner> mLifecycleOwner;
private int mAddingObserverCounter = 0;
private boolean mHandlingEvent = false;
private boolean mNewEventOccurred = false;
// we have to keep it for cases:
// void onStart() {
// mRegistry.removeObserver(this);
// mRegistry.add(newObserver);
// }
// newObserver should be brought only to CREATED state during the execution of
// this onStart method. our invariant with mObserverMap doesn't help, because parent observer
// is no longer in the map.
private ArrayList<State> mParentStates = new ArrayList<>();
...............................
...............................
/**
* Sets the current state and notifies the observers.
* <p>
* Note that if the {@code currentState} is the same state as the last call to this method,
* calling this method has no effect.
*
* @param event The event that was received
*/
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
State next = getStateAfter(event);
moveToState(next);
}
private void moveToState(State next) {
if (mState == next) {
return;
}
mState = next;
if (mHandlingEvent || mAddingObserverCounter != 0) {
mNewEventOccurred = true;
// we will figure out what to do on upper level.
return;
}
mHandlingEvent = true;
sync();
mHandlingEvent = false;
}
private boolean isSynced() {
if (mObserverMap.size() == 0) {
return true;
}
State eldestObserverState = mObserverMap.eldest().getValue().mState;
State newestObserverState = mObserverMap.newest().getValue().mState;
return eldestObserverState == newestObserverState && mState == newestObserverState;
}
private State calculateTargetState(LifecycleObserver observer) {
Entry<LifecycleObserver, ObserverWithState> previous = mObserverMap.ceil(observer);
State siblingState = previous != null ? previous.getValue().mState : null;
State parentState = !mParentStates.isEmpty() ? mParentStates.get(mParentStates.size() - 1)
: null;
return min(min(mState, siblingState), parentState);
}
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
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 = calculateTargetState(observer);
mAddingObserverCounter++;
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
if (!isReentrance) {
// we do sync only on the top level.
sync();
}
mAddingObserverCounter--;
}
......................................
.....................................
}
从LifecycleRegistry实现我们不难发现,LifeCycleEvent最终通过一系列注册的Observer将Event事件分发出去,这种方式也是我们设计观察者模式的基本方式,那么接下来,我们再分析下LiveData是如何将Observer注册到LifecycleRegistry中的。
前面我们在获取会议列表时,实际上已经注册了一个Observer,代码如下:
registerObserver(Constants.EVENT_KEY_QUERY_CONF_LIST, ConfListVo.class).observe(this,
new Observer<ConfListVo>() {
@Override
public void onChanged(@Nullable ConfListVo confListVo) {
if(confListVo != null){
QueryListResult result = confListVo.queryListResult;
if(result != null){
Log.d(TAG,"has Conf summary result.");
showConferenceList(result.getSqSummaryList());
}
}
}
});
public static class LiveBusData<T> extends MutableLiveData<T> {
private boolean isFirstSubscribe;
LiveBusData(boolean isFirstSubscribe) {
this.isFirstSubscribe = isFirstSubscribe;
}
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, new ObserverWrapper<>(observer, isFirstSubscribe));
}
}
MutableLiveData继承自LiveData, 所以最终会调用LiveData中的observe方法将Observer加入到LifecycleRegistry的Observer列表中,该Observer被加入列表之前被加工成了LifecycleBoundObserver类,也就是和生命周期状态关联了起来,从而具有生命周期感知能力, 这里不做详细展开,有兴趣可以去详细去分析其源码。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
在获取到实际数据后,我们通常会调用LiveData的postValue(T value)
与setValue(T value)
, postValue(T value)
执行后会在主线程中调用Observer的void onChanged(@Nullable T t)
方法, 而setValue(T value)
执行后则只会在被调用线程中执行void onChanged(@Nullable T t)
方法。 postValue(T value)
最终还是调用setValue(T value)
完成Observer回调。在执行回调流程中,这些Observer实际上已经保存了生命周期的状态,从而只有Active的Observer才能被回调更新,而处于非Active状态的Observer将得不到更新。
3.2 数据更新过程及类图实现
触发Observer回调的方法有两种,一种是Activity/Fragment生命周期发生了变化,一种是调用了setValue()/postValue()方法。具体调用流程如下图所示,具体代码可以参考LiveData及LifecycleRegistry源码(support 26.1.0以上)
触发Observer调用的流程图
实现LifeCycle感知能力组件类图实现
生命周期感知实现的类图结构
4. 总结
4.1 LiveData如何做到感知Activity/Fragment的生命周期的?
从前面分析,我们可以总结如下:
首先, Activity/Fragment是LifecycleOwner(26.1.0以上的support包中Activity已经默认实现了LifecycleOwner接口),内部都会有一个LifecycleRegistry存放生命周期State、Event等。
其次,最核心的是每个Activity在启动时都会自动添加进来一个ReportFragment,由于添加进来的Fragment与Activity的生命周期是同步的,所以当Activity执行相应生命周期方法的时候,同步的也会执行ReportFragment的生命周期方法, 从而将相应的生命周期事件分发给注册到LifecycleRegistry的Observer。ReportFragment对于开发者来说是隐藏,开发者只需要将待观察的LiveData注册一个Observer。
最后,将LiveData注册一个监听,从而该数据具有了生命周期感知的能力。
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
...
...
owner.getLifecycle().addObserver(wrapper);//注册对Activity/Fragment生命周期的监听
}
4.2 LiveData如何做到避免内存泄漏的呢?
当Activity/Fragment的生命周期发生改变时,LiveData中的监听都会被回调,所以避免内存泄漏就变得十分简单,在”触发Observer调用的流程图“中可以看到,当LiveData监听到Activity onDestory时则removeObserve,使自己与观察者自动解绑。这样就避免了内存泄漏, 代码如下。
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
4.3 LiveData如何避免View空异常的问题?
从”触发Observer调用的流程图“中可以看到, LiveData响应(比如更新界面操作View)只会在界面可见的时候,如果当前见面不可见,则会延迟到界面可见的时候再响应,所以自然就不会有View空异常的问题了。
那么LiveData是如何实现:
只在界面可见的时候才响应的
如果当前界面不可见,则会延迟到界面可见的时候再响应
对于第一点,因为LiveData是能感知到生命周期的,所以在它回调响应的时候会加一个额外的条件,就是当前的生命周期必须是可见状态的,才会继续执行响应,源码如下:
private void 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);
}
对于第二点, LiveData引入了数据版本号的概念来加以实现, 在LiveData中有一个全局变量mVersion,而每个observer中有一个变量mLastVersion。当我们每次setValue()修改一次LiveData的值的时候,全局的mVersion就会+1,这样mVersion就大于mLastVersion:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
而当界面重新可见的时候,只要判断到mVersion大于mLastVersion,则就会进行响应刷新View,响应后才会更新mLastVersion=mVersion。
private void 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);
}
实际上LiveData是一种粘性的实现,其原理也是基于Data Version,通过对比Observer与LiveData的版本决定是否执行Observer回调。
在ViewModel的作用主要是实现跟UI相关数据的保存,在其实现代码中,我们发现其生命周期感知也是通过在Activity/Fragment中通过FragmentManager加入了一个无界面的Fragment来感知生命周期变化,从而决定ViewModel的创建与复用,有兴趣的同学可以跟下源码。