Android Architecture Components源码分析
在分析Android Architecture Component这个框架之前,先想想这个框架能为我们做什么,我们为什么要按照这套框架模式去构建app?它和MVP架构有什么区别?
MVP, Clean, AAC架构的特点:
MVP架构的特点是面向接口编程。在View, Presenter, Model之间分别用接口做衔接,当有新的底层实现时,能够无缝替换。
此外,MVP的View和Model并不产生依赖,因此可以说是对View和Model做了解耦。
但MVP架构有其局限性。MVP需要创建太多的类和接口,并且每次通信都需要繁琐的通过接口传递信息
google sample提供了一个todo-mvp sample, 里面有MVP+RxJava实现,Clean架构实现。这两种架构方式我都实践过,MVP+RxJava所有业务,UI逻辑都包含在Presenter里面, Presenter直接干预了UI在拿到数据后做什么,使得逻辑上没有发生解耦,正常来说,解耦意味着Presenter的只能边界仅限返回结果数据,由UI来根据数据处理UI逻辑。
Clean架构将业务逻辑分解成可重用的更小粒度的usecase, 业务逻辑的职能被转移到领域层,Presenter则弱化为ViewModel, 作为代理数据请求和衔接数据回调的缓冲区。
Clean 架构的特点是单向依赖、数据驱动编程。 View -> ViewModel -> Usecase -> Model.
但 Clean 架构也有不足:粒度太细 。一个 Usecase 受限于请求参数,因而只能处理一类请求。View请求求的数据包含几种类型,就至少需要准备几个 Usecase。Usecase是依据当前View对数据的需求量身定制的,且形式大同小异,因此Usecase的复用率极低,项目会因而急剧的增加类和重复代码。
AAC也是数据驱动编程。直接在View中写个观察者回调,以接收结果数据并处理UI逻辑。MVP架构中Presenter直接引用View,告诉View该显示什么,而AAC中的View持有ViewModel的引用,ViewModel不需要持有View的引用,而是根据View绑定的事件进行流式调用,这也意味着MVP架构中以来的回调接口也用不着了。
数据的消费者应该知道生产者,但生产者(ViewModel)不知道也不关心谁消费了数据。
1 | private void subscribeUi(ProductListViewModel viewModel) { |
除此之外,Fragment.setRetainInstance(boolean retain
)方法设置为true, 保证Configuration change的时候与该fragment关联的数据能够保存。
AAC是由一系列库组成,能够帮助我们管理UI组件的生命周期和处理数据存留。生命周期感知组件可以管理Activity和Fragment的生命周期,在configuration change的时候可以保留现场数据并重新更新UI,避免内存泄漏。
使用LiveData构造数据对象,当底层数据发生变化时就会通知更新UI.
ViewModel存储UI相关的数据,在app旋转时不会销毁。
Lifecycle如何与Activity, Fragment的生命周期绑定?
Lifecycle定义了一个拥有Android生命周期的对象,Activity, Fragment实现了LifecycleOwner接口,可以直接访问到Lifecycle.
1 | public class ComponentActivity extends Activity |
Lifecycle定义了两个枚举类型Event和State, State可以看做图的节点,State定义了一系列与生命周期相关的状态,Event则可以看做图的路径。Lifecycle负责保存并更新当前生命周期状态。
刚好在Activity.onDestroy()调用之前,达到DESTROYED状态,处于DESTROYED状态的Lifecycle对象不会再传递任何事件Event.
INITIALIZED状态在Lifecycle对象已创建但还未调用Activity.onCreate()之前。
在Activity.onCreate()调用之后,Activity.onStop()调用之前处于CREATED状态。
在Activity.onStart()调用之后,Activity.onPause()调用之前处于STARTED状态。
在Activity.onResume()调用之后处于RESUMED状态。
接下来看看状态的转化。
什么时候处于INITIALIZED状态呢?
首先来看一下生命周期感知组件的类关系图
Lifecycle定义成一个拥有Android生命周期的接口对象。Fragment或FragmentActivity实现了LifecycleOwner接口,并通过getLifecycle方法获取LifecycleRegistry对象。LifecycleRegistry实现了Lifecycle,能够处理多个观察者。
LifecycleRegistry定义了内部嵌套类ObserverWithState,通过调用addObserver方法我们将参数LifecycleObserver对象传入,并封装成了ObserverWithState对象,在handleLifecycleEvent接收到外部传入的Event事件,计算出目标状态,最后调用GenericLifecycleObserver的onStateChanged方法通知状态的变换。
当应用程序启动时,会注册清单文件里声明的ContentProvider, 在框架里就是ProcessLifecycleOwnerInitializer, 可以到app/build/outputs/logs/manifest-merge-debug-report.txt找到ProcessLifecycleOwnerInitializer类所在的清单文件位置,最终清单文件会合并到打包完成的应用中来。
1 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
ProcessLifecycleOwnerInitializer只干一件事,注册ActivityLifecycleCallbacks,具体是使用一个无UI的ReportFragment, 利用Fragment的生命周期回调将Lifecycle Event发布出去。
1 | public class ProcessLifecycleOwnerInitializer extends ContentProvider { |
ProcessLifecycleOwner提供了整个应用进程的生命周期,Lifecycle.Event.ON_CREATE事件只会发布一次,而Lifecycle.Event.ON_DESTROY则不会发布。Lifecycle.Event.ON_PAUSE和Lifecycle.Event.ON_STOP事件则会在上一个Activity走完对应生命周期方法后延时发布。这个延时时间足够长,确保当configuration change导致Activity销毁,重建时不会重新发布对应事件。
当我们需要监听应用从后台回到前台或者从前台到后台时,这个类就变得很有用。
我们可以在自定义Application中添加观察者,监听到ON_START事件表示应用回到前台,监听ON_STOP事件表示应用回到了后台。
1 | public class BasicApp extends Application { |
根据上图我们再来梳理一下ProcessLifecycleOwner发布消息的流程。
1.程序启动时,ProcessLifecycleOwner完成初始化,注册ActivityLifecycleCallbacks, 对ReportFragment设置监听器处理Fragment对应的onStart(), onResume()回调。
2.用户启动Activity, ReportFragment通过回调通知ProcessLifecycleOwner发送Lifecycle.Event.ON_START事件,并将计数器mStartedCounter加1,mStopSent置为false. 接下来收到onResume()回调,将计数器mResumedCounter加1,发送Lifecycle.Event.ON_RESUME事件,mPauseSent置为false.
3.用户启动一个新的Activity, ProcessLifecycleOwner注册的ActivityLifecycleCallbacks收到onActivityPaused回调,将计数器mResumedCounter减1,并将Lifecycle.Event.ON_PAUSE事件延时处理。如果在这段事件内configuration change导致Activity销毁并重建的话,那么计数器mResumedCounter, mStartedCounter值将发生改变,Lifecycle.Event.ON_PAUSE, Lifecycle.Event.ON_STOP事件将不会发布。当应用最后一个Activity销毁的时候,就会发布Lifecycle.Event.ON_STOP事件。
1 | void activityResumed() { |
FragmentActivity继承自ComponentActivity,ComponentActivity会初始化LifecycleRegistry对象并在onCreate方法里会创建一个ReportFragment. 而LifecycleDispatcher里注册的ActivityLifecycleCallbacks也会在onActivityCreated方法中初始化ReportFragment, 将这个无UI的Fragment添加到FragmentActivity中,监听activity生命周期的变化。
1 | public class ComponentActivity extends Activity |
Lifecycle内部定义了State和Event两个枚举类型,代表了组件所处的生命周期状态和即将变换状态的事件。下图清晰说明了状态的变化过程。
LifecycleRegistry初始化时的状态是INITIALIZED, FragmentActivity或者Fragment在生命周期方法执行时会调用handleLifecycleEvent方法完成目标状态的转换。在这个过程中,通过调用
1 | mLifecycleObserver.onStateChanged(owner, event) |
会将新的状态发布给订阅者。
值得注意的是,State状态是递增变化的。
1 |
|
例如,在onResume方法中添加LifecycleBoundObserver,调用LifecycleRegistry.addObserver方法,initialState为INITIALIZED, 根据当前的状态计算出targetState为STARTED, 然后在while循环中将INITALIZED至STARTED中的所有状态依次发送出去。
1 |
|
ObserverWrapper通过mActive标记和mLastVersion变量跟踪状态和数据的变化,对于LifecycleBoundObserver来说只有当State是STARTED才能将数据发送出去,如果State为DESTROYED状态的时候则会移除Observer. 当LiveData的version大于OberverWrapper的version时,会将最新的数据发送出去。
1 | private abstract class ObserverWrapper { |