基于Google架构组件的MVVM实现

1. mvvm简介

1.1 概述

现在MVP架构在应用开发中普遍使用,但是随着业务的增加,其暴露的缺点也越来越明显,总结起来有以下几点:

  1. 随着业务的增加,接口暴增,代码成倍增长,所有交互都需要通过接口传递信息,对开发者造成困扰;
  2. Presenter作为UI和Model层的桥梁,造成Presenter臃肿,维护困难;
  3. 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 平台的一部分。这就意味着,我们可以根据自己的需求采用每一个组件。

Android Jetpack

对于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框架

  1. 先定义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,同时方便切换数据来源。

  1. 定义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和网络请求订阅容器,方便管理网络请求,即页面销毁是取消网络请求操作。

  1. 定义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.Fragmentandroid.support.v4.app.FragmentActivity, 因为这两个类默认已经实现了LifeCycles组件接口,所以其承载的LiveData及ViewModel具备了生命周期感知能力,具体实现后面会讲到。

2.2 MVVM使用实例

下面以获取会议列表的业务来演示下该MVVM框架的使用, 步骤如下:

  1. 实现获取会议列表的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());

                          }
                        }
                    }
                });
    }
  ..................................
  ..................................

  1. 实现获取会议列表的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);
    }

}
  1. 实现获取会议列表的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架构实现
下图展示了MVVM架构App包结构
MVVM架构包结构

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的创建与复用,有兴趣的同学可以跟下源码。

猜你喜欢

转载自blog.csdn.net/u011897062/article/details/85214756