Jetpack之一:Lifecycle
在介绍Lifecycle之前我们先了解一下Jetpack。
Android已经发展了15年,可以说是比较成熟的技术了,一开始时框架很少,也没有什么规范,所有的代码都是要自己写,比如网络请求,数据库请求,数据解析等等。后来出现了一些框架来帮助开发者快速进行开发,比如XUtils、Volley、OKHttp、EventBus等,随着框架越来越多,一个应用可以有多种技术选型,直接导致应用开发越来越不规范,导致做出来的应用质量参差不齐,这显然不是谷歌想看到的。谷歌随后推出了MVP和MVVM相关的官方例子,效果很一般,而且覆盖只是在架构上,Goole I/O 2018大会上推出的Android Jetpack有望解决以上的问题。
在此之前,相信大家都已经学过Kotlin了,本节课也全采用Kotlin教学。
1.jetpack是什么?
Jetpack就是Google官方推出的一套方便开发者的库。
Android Jetpack 开发资源 - Android 开发者 | Android Developers (google.cn)

Android Jetpack 组件覆盖以下 4 个方面:
Foundation (基础组件)
- AppCompat:使得支持较低的 Android 版本。从以前继承 Activity 到现在继承AppCompatActivity 就是属于这一部分
- Android KTX:Kotlin 的扩展支持库
- Multidex:多 dex 文件支持
- Test:测试支持库
Architecture (架构组件)
- DataBinding:MVVM 的一种实践
- Lifecycle:管理你的 Activity 和 Fragment 生命周期
- LiveData:通过观察者模式感知数据变化,类比 RxJava
- Navigation:处理 Fragment 导航相关逻辑
- Paging:分页数据加载方案
- Room:官方数据库
- ViewModel:通过数据驱动 V 视图发生改变
- WorkManager:管理后台任务
Behavior (行为组件)
- DownloadManager:管理下载任务
- Media App:多媒体播放和一些向后兼容的API。主要包含 MediaPlayer 和 ExoPlayer
- Notifications:提供向后兼容的通知 API,支持 Wear 和 Auto
- Permissions:权限管理,这个应该都接触过。用于检查和请求应用权限
- Settings:Preference 相关 API。基本每个应用都会用到
- Share Action:提供分享操作。这块在国内使用的不多,都是自己封装或者采用第三方方案
- Slices:可以让应用通过外部(其他 APP)显示 APP 界面(通过设备自带的搜索,语音助手等)
UI (界面组件)
- Animations and Transitions:动画,界面转场等
- Auto:针对车辆的标准化界面和模式
- Emoji:表情符号相关
- Fragment:基础概念
- Layout:基础概念
- Palette-Colors:调色板
- TV:Android TV 开发相关
- Wear:可穿戴设备(目前主要是手表)开发相关
官方描述:
2.为什么使用Jetpack?
遵循最佳做法
Android Jetpack 组件采用最新的设计方法构建,具有向后兼容性,可以减少崩溃和内存泄露。消除样板代码
Android Jetpack 可以管理各种繁琐的 Activity(如后台任务、导航和生命周期管理),以便您可以专注于打造出色的应用。减少不一致
这些库可在各种 Android 版本和设备中以一致的方式运作,助您降低复杂性。
3.jetpack的使用
在使用之前,先添加依赖,打开项目根目录的build.gradle,添加google(),如下:
allprojects { |
之后在你需要使用jetpack组件的模块的build.gradle里添加依赖,比如我要使用lifecycle:
dependencies { |
最新的版本请查看Android官网,之后就是最爽的调包环节了。
上面讲到jetpack分为四个板块,包含了很多组件,但是常用的只有几个:
- LiveData
- ViewModel
- Lifecycle
- Room
- Navigation
- DataBinding/ViewBindingg
- Paging
- Dagger2/Hilt
本节课只讲解lifecycle,DataBinding/ViewBindingg ,livedata,viewmodel,navigation。Room下节课会给你们讲。paging的话一般是上拉加载,下拉刷新会用到,这里有时间的话可以讲一讲。
lifecycle
因为livedata,viewmodel都是基于lifecyccle基础上的,所有先讲讲lifecycle。
1.什么是lifecycle?
生命周期感知型组件可执行操作来响应另一个组件(如 activity 和 fragment)的生命周期状态的变化。这些组件有助于您写出更有条理且往往更精简的代码,这样的代码更易于维护。
2.为什么需要lifecycle?
我们知道Activity和fragment是由生命周期的,onCreate,onStart,onResume,onPasue,onStop,onDestroy等等。在开发中我们避免不了和他们打交道。比如,现在给你一个需求,要你写一个定时器,在页面退出到主界面时停止计时,你要怎么做?写一个回调在onPasue里面?确实是可以。但是时间一长,功能需求一多,Activity避免不了臃肿,而且处理不好还容易发生内存泄漏。什么是内存泄漏?简言之就是该被回收的对象未被回收。比如一个Activity已经被销毁了,这时候Activity这个对象应该被回收但是被你的回调引用却未被回收,这就是内存泄漏,原理这里就不多讲。因此我们需要一个能管理Activity和Fragment的生命周期的库,这个库就是Lifecycle。
3.使用
先构建Observer,字面意思就是观察者,感知生命周期肯定是观察者,被观察者就是拥有生命周期的组件,一般是Activity和Fragment
方法一,实现DefaultLifecycleObserver:
/** |
再在activity中添加
class MainActivity : AppCompatActivity() { |
日志:
方式二,实现LifecycleEventObserver:
/** |
在Activity添加:
class MainActivity : AppCompatActivity() { |
日志:
这么来看。lifecycle的使用还是很简单的,作为jetpack很多组件的基础组件,我们有必要了解一下它的原理。
4.原理
相信大家这也是第一次看框架的源码,可能会有点绕,但是多看看还是能理解的,源码就是要多看,越看越简单。
看源码一个比较好的方法就是带着问题去看,就是为什么去看。为什么?我们想知道lifecycle是怎么感知activity生命周期的嘛。
那我们先来看我们刚刚写的代码,很简单,就是定义了一个observer,然后在activity里面getlifecycle.addObserver就完事了。
那我们先来看addObserver。
lifecycle.addObserver(MyObserver()) |
要看addObserver,肯定要看看调用者是是谁,是lifecycle,我们点进去看看
那我们再看看mLifecycleRegistry是怎么个事。
是个lifecycleRegistry,并且创建的时候把当前activity传了进去。我们看一看:
他将我们当前的activity用weakRefernce进行引用了,weakReference是什么,是java里的弱引用。java里的引用分为强引用,软引用,弱引用,和虚引用。强引用就是我们常见的直接用对象点调用他的属性,这里用弱引用是为了防止内存泄露,具体原理这里就不讲了,打脑壳。然后初始化了mState为初始状态。这里参数用的是lifecycleOwner,那说明我们的activity肯定是实现了lifecycleowner的。我们看一看:
确实实现了lifecycleowner,而lifecycleowner仅仅是一个接口,提供了获取lifecycle的方法:
ok,再MainAvtivity里面,我们用lifecycle.addObserver的lifecycle怎么来的我们搞清楚了。现在我们看看addObserver,
也就是LifecycleRegistry的addObserver:
|
我们先不看一些null和false或true的判断。我们看看我们传进来的Observer也就是我们定义的MyObserver他干了什么?首先在注释1处他把我们的Observer包装成了ObserverWithState,然后在注释2处把封装起来的ObserverWithState和observer放到mObserverMap里面。3和4分别就是计算状态和判断mObserverMap是否添加过observer。看来就是把我们的observer封装起来用了。那我们再来看看,这里面做了什么事情,首先再4行的地方初始化state,之后在11行获取了刚刚弱引用引用的lifecycleowner也就是我们的activity,之后将observerCount++。最后是有个while循环,这个循环有什么用呢?我们先来看我们一开始在哪里addObserver的,在onCreate对吧。那有没有想过,我可不可以在onStart,onResume的其他生命周期addObserver呢?是可以的。那假如说我在onResume里面addObserver,前面的onCreate,onStart生命周期我们的MyObserver能感知吗?能!原因就在这个while循环,它会逐步将之前的生命周期回调,具体回调方法在statefulObserver.dispatchEvent(lifecycleOwner, event);里面。我们点进去看看:
其实回调的就是mLifecycleObserver.onStateChanged(owner, event);,有没有很熟悉?我们好像重写过这个方法把。mLifecycleObserver就是:
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); |
我们可以点进lifecycleEventObserver看,其实就是返回LifecycleEventOberver或者FullLifecycleObserver,就是将我们自己写的observer转换了一下:
而FullLifecycleObserverAdapter内部也是调FullLifecycleObserver对应的生命周期方法,也就是我们MyObserver重写的方法:
OK,现在addObserver我们看差不多了,但这仅仅是addObserver的一些处理,那我们的MyObserver是怎么感知Activity的周期的呢?我们刚刚寻找lifecycle在哪里创建的时候知道,它是在ComponentActivity里面创建的,而我们的MainActivity也是继承自ComponentActivity并且实现了LifecycleOwner,那感知生命周期肯定在ComponentActivity的生命周期里做了手脚,我们看一看:
果然,在他的onCreate有这么一行代码:
ReportFragment.injectIfNeededIn(this); |
我们跟进看一看:
在API29之后注册了一个LifecycleCallbacks并且吧当前activity传了进去,在老版本是添加了一个ReportFragment到当前ACtivity,添加了一个没有界面的Fragment,那我们看看这个Fragment:
分别在对应的生命周期dispatch,我们知道Fragment的生命周期是随Activity变化的,Activity onResumeFragment也肯定onResume了,好家伙原来是用一个无形的Fragment寄生在ACtivity上去感知Activity的生命周期的,原来如此,那我们再看看dispatch干了什么:
如果是LifecycleRegistryOwner就getLifecycle然后调用handleLifecycleEvent,这里的getLifecycle就是LifecycleRegistry和下面是一样的,那我们看看LifecycleRegistry的handleLifecycleEvent:
抛去其他null和状态判断,我们看关键的sync():
分别调用了两个关键的方法:backwardPass和forwardPass并把当前的lifeCycleOwner传了进去,字面意思就是向前,向后移动,就是根据当前的生命周期和即将发生的生命周期进行相减以判断是前移还是后移,onCreate,onStart,onResume就是往前,反之往后,两者差不多,我们就拿向后看看:
private void backwardPass(LifecycleOwner lifecycleOwner) { |
首先就是获取我们在addObserver里面创建的ObserverWithState,也就是我们的MyObserver,然后在2处获取下一个事件:
|
这个结合要结合宿主的生命周期和LifeCycle的state来看:
最后在3处调用observer的dispatchEvent,然后while循环一步一步回调至对应的生命周期,再看看observer.dispatchEvent(lifecycleOwner, event):
当当当,就是回调我们自己写的MyObserver了,到此我们就明白了,其实就是用一个无形的Fragment寄生Activtiy去感知,那我们再看看API 29之后:
其实就是API29之后 Application提供了监听acitvity生命周期的方法,之后就是调用ReportFragment的dispatch。至此,lifecycle的源码分析结束了,整体看来还是比较简单的,就是一些回调。