前言

谷歌官方推的Jetpack框架也已经有很长一段时间了,基本上新开的项目都会使用MVVM + kotlin + 协程的架构去搭建一些新的项目或者重构,因此面试中AAC框架在面试或多或少会提到,本篇主要是对几个常用框架进行高度概括,具体需要自行结合源码查阅

Lifecycle

  • 功能:抽离Activity生命周期,提供API进行监听(观察者模式),使用状态模式保存了当前的状态以及前后两步的事件
  • 注意点:非线程安全,在主线程调用
  • 源码实现:在ComponentActivity会注入一个ReportFragment,里面会对生命周期进行分发(类似Glide)
  • 注解(OnLifecycleEvent)使用原理:
  • 2.4 之后已废弃,推荐设置监听的方式实现
  • 实现LifecycleObserver接口,这个接口是个空接口,之后在需要的方法标记OnLifecycleEvent注解,例如 @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) ,然后调用 Lifecycle#addObserver 方法,里面会构造一个 ObserverWithState,在ObserverWithState的构造函数会调用 Lifecycling#lifecycleEventObserver,通过注解反射获取到所有标注了的方法,在分发生命周期的时候会通过反射调用该方法
  • 通过ObserverWithState 以及 Lifecycling 统一了注解/继承 接口,以便调用;在其dispatchEvent方法会获取

状态与事件

分发流程image-20220524174909957.png

LiveData

  • 功能:
  1. 具有观察生命周期能力的数据,本身观察Lifecycle,并且提供API作为被观察者监听数据变化(仅在生命周期有效时触发)
  2. 作为事件总线使用 —— LiveDataBus
源码分析
Observe 方法
  • 首先根据调用的observe或者observeForever,对监听对象进行一次包装,然后添加到观察者集合,这里的包装是为了后续的统一操作(判断是否活跃等);一个监听对象只能对应一个lifecycle
  • 接着如果是observeForever,会调用检查一次值状态进行分发(黏性);如果是observe方法,则会封装成LifecycleBoundObserver(实现了LifecycleEventObserver),并添加监听Livecycle的事件,后续会根据事件决定是否分发新值(活跃状态)

image-20220525232613966.png

分发消息
  • postValue(切换到主线程再调用setValue)
  • setValue

无论是postValue还是 setValue,都会走到setValue,首先会更新LiveData的值,然后把版本号加一,再遍历所有观察者,判断生命周期并调用符合条件的观察者的onChange方法,注意这个遍历的过程,当所绑定的生命周期状态改变时也会进行一轮判断(ObserverWrapper#activiStateChange)

// mDispatchingValue: 是否正在分发值
// mDispatchInvalidated 是否分发完成
// 通过这两个状态控制分发状态 及时更新最新的值
void dispatchingValue(@Nullable ObserverWrapper initiator) {
        // 如果正在更新值 mDispatchInvalidated 直接置为true 这样下面do while会再执行一次 更新最新的值
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    // 说明有新值 直接中断重新开始
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
    
 // 真正的把值传递出去
 private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
      
        // 对观察者状态再次判断
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // 避免重复调用
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

image-20220525231247043.png

事件总线用法
  • 可以将LiveData 以Map的形式存储起来,当做事件总线使用,但是有个问题是默认的消息是黏性的(数据倒灌)
  • 解决方法:数据倒灌的原因是添加观察者的时候,此时会更新Lifecycle的状态,进一步同步值;此时可以通过反射修改Observer的Version值和LiveData的一样,这样就不会触发更新了

image-20220526175752195.png

ViewModel

  • 功能:在MVVM中的VM层,隔离View和Model,同时具有生命感知能力,能够在系统配置发生变更(旋转等)自动保存数据,同时提供clear方法在activity销毁的时候清除数据
  • 保存复用:利用ComponentActivity#onRetainNonConfigurationInstanceComponentActivity#getLastNonConfigurationInstance,在activity消耗重建的时候重新赋值了一个ViewModelStore,这个ViewModelStore实际上是一个存放ViewModel的Map(String-ViewModel),而在获取ViewModel的时候,也是在这个ViewModelStore去取,如果有则返回,没有的话则通过反射去创建一个并保存在这个Map中
  • 销毁监听:在ComponentActivity 创建时会注册一个LifecycleEvent监听,当收到 销毁事件且不是配置变更时 ,会调用ViewModelStore的clear方法,之后就是依次遍历调用clear的流程
  • ViewModelStore的消耗:和onClear一样也是监听了lifecycleEvent,收到销毁事件清空

image-20220527123903985.png
image-20220527123917221.png

StartUp

  • 功能:初始化组件,背景是多种三方SDK利用ContentProvider的生命周期进行初始化,导致启动响应变慢(Application#attachBaseContext -> ContentProvider#onCreate -> ),因此推出StartUp进行统一管理
  • 支持自动/手动 初始化;支持设置依赖关系;
  • 自动初始化:配置provider时设置meta值
  • 手动初始化:AppInitializer.getInstance(this).initializeComponent(xxx.class)
  • 原理概括:使用ContentProvider聚合了初始化插件
  • 使用及原理参考

汇总图

请添加图片描述

常见面试题

MVP和MVVM优势和劣势
  • MVP:从MVC中演化,进行解耦,和View层分离,减少Activity的负担;但是MVP会产生大量的接口和类文件;生命周期需要自己管理;View和P层耦合度较高,常常需要配合改动
  • MVVM:M层完全关注于数据;更加的低耦合,VM不持有View相关,而且很多业务逻辑可以放在VM层复用;但是Databinding会导致XML文件难以复用并且难以Debug
  • 最大的区别是在MVP中,P和V层是互相持有的,而在MVVM中,VM是不持有View,不再依赖View层,而是通过观察者模式观察数据变化(LiveData、DataBinding等)
ViewModel保存在Application和ViewModelScope的区别

生命周期的区别,一个是应用的生命周期一个是lifecycle的生命周期

ViewModel如何保证Activity销毁后保存数据

在Activity被销毁的时候,AMS会通过远程Binder调用 retainNonConfigurationInstances 方法,这个方法会调用onRetainNonConfigurationInstancegetLastNonConfigurationInstance 保存一些配置,其中就包括 ViewModelStore ,在重新创建Activity时,AMS会通过 AMS#attach 将这个实例重新赋值

ViewModelProvider和ViewModelProviders

ViewModelProviders 是早期用于创建ViewModel的,新版本已经弃用,直接使用ViewModelProvider创建,对应的ViewModelStore也是由Activity/Fragment管理

ViewModel的保存和恢复

见上ViewModel篇

如何理解MVVM
  • 首先MVVM是一种架构模式,在安卓开发中,谷歌为我们提供了一套jetpack框架用于快速实现MVVM(LiveData、Databinding、ViewModel),其中里面为我们处理了很多生命周期相关的重复性工作,消除了大量的重复代码
  • AAC框架里面的核心我认为是Lifecycle,以Activity为例,是通过注入一个无UI的fragment,获取到生命周期的事件,再在里面维护了一个状态机,而且LiveData、ViewModel等的生命周期感知能力都是通过Lifecycle维护的这个状态去控制的
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐