Jetpack AAC 系列文章:
“终于懂了“系列:Jetpack AAC完整解析(一)Lifecycle 完全掌握!
“终于懂了“系列:Jetpack AAC完整解析(二)LiveData 完全掌握!
“终于懂了“系列:Jetpack AAC完整解析(三)ViewModel 完全掌握!
欢迎关注我的 公 众 号,微信搜索 胡飞洋 ,文章更新可第一时间收到。
一、Android Jetpack 介绍
1.1 Jetpack是啥
官方定义如下:
Jetpack 是一个由多个库组成的套件,可帮助开发者遵循最佳做法,减少样板代码并编写可在各种 Android 版本和设备中一致运行的代码,让开发者精力集中编写重要的代码。
JetPack更多是一种概念和态度,它是谷歌开发的非Android Framework SDK自带、但同时是Android开发必备的/推荐的SDK/开发规范合集。相当于Google把自己的Android生态重新整理了一番,确立了Android未来的开发大方向。
使用Jetpack有如下好处:
- 遵循最佳做法,Android Jetpack 组件采用最新的设计方法构建,具有向后兼容性,可以减少崩溃和内存泄露。
- 消除样板代码,Android Jetpack 可以管理各种繁琐的 Activity(如后台任务、导航和生命周期管理),以便您可以专注于打造出色的应用。
- 减少不一致,这些库可在各种 Android 版本和设备中以一致的方式运作,助您降低复杂性。
Jetpack原意为 喷气背包,Android背上Jetpack后就直冲云霄,这很形象了~
也就是,Jetpack是帮助开发者高效开发应用的工具集。那么这一工具包含了哪些内容呢?
1.2 Jetpack分类
分类如下图(现在官网已经找不到这个图了):
Android Jetpack 组件覆盖以下 4 个方面:架构(Architecture)、基础(Foundation)、行为(Behavior) 、界面(UI)。
真正的精华主要是Architecture,全称是Android Architecture Component(AAC), 即Android架构组件。
其包括比较成功的Lifecycle、LiveData、ViewModel,同时也是我们使用MVVM模式的最好框架工具,可以组合使用,也可以单独使用。
以上基本都是官网的介绍,我们主要目标就是掌握AAC的组件,深入理解进而运用到MVVM架构中。
如题,我们学习Jetpack的重点就是AAC,这篇就从基础的Lifecycle讲起。
二、Lifecycle
Lifecycle,顾名思义,是用于帮助开发者管理Activity和Fragment 的生命周期,它是LiveData和ViewModel的基础。下面就先介绍为何及如何使用Lifecycle。
2.1 Lifecycle之前
官方文档有个例子 来说明使用Lifecycle之前是如何生命周期管理的:
假设我们有一个在屏幕上显示设备位置的 Activity。常见的实现可能如下所示:
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) {
// ...
}
void start() {
// 连接系统定位服务
}
void stop() {
// 断开系统定位服务
}
}
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
@Override
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// 更新 UI
});
}
@Override
public void onStart() {
super.onStart();
myLocationListener.start();
// 管理其他需要响应activity生命周期的组件
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
// 管理其他需要响应activity生命周期的组件
}
}
虽然此示例看起来没问题,但在真实的应用中,最终会有太多管理界面和其他组件的调用,以响应生命周期的当前状态。管理多个组件会在生命周期方法(如 onStart() 和 onStop())中放置大量的代码,这使得它们难以维护。
此外,无法保证组件会在 Activity 或 Fragment 停止之前启动myLocationListener。在我们需要执行长时间运行的操作(如 onStart() 中的某种配置检查)时尤其如此。在这种情况下,myLocationListener的onStop() 方法会在 onStart() 之前调用,这使得组件留存的时间比所需的时间要长,从而导致内次泄漏。如下:
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// 更新 UI
});
}
@Override
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
//如果checkUserStatus耗时较长,在activity停止后才回调,那么myLocationListener启动后就没办法走stop()方法了,
//又因为myLocationListener持有activity,所以会造成内存泄漏。
if (result) {
myLocationListener.start();
}
});
}
@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}
即2个问题点:
- activity的生命周期内有大量管理组件的代码,难以维护。
- 无法保证组件会在 Activity/Fragment停止后不执行启动
Lifecycle库 则可以 以弹性和隔离的方式解决这些问题。
2.2 Lifecycle的使用
Lifecycle是一个库,也包含Lifecycle这样一个类,Lifecycle类 用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。
2.2.1 引入依赖
1、非androidX项目 引入:
implementation "android.arch.lifecycle:extensions:1.1.1"
添加这一句代码就依赖了如下的库:
2、androidX项目 引入:
如果项目已经依赖了AndroidX:
implementation 'androidx.appcompat:appcompat:1.2.0'
那么我们就可以使用Lifecycle库了,因为appcompat依赖了androidx.fragment,而androidx.fragment下依赖了ViewModel和 LiveData,LiveData内部又依赖了Lifecycle。
如果想要单独引入依赖,则如下:
在项目根目录的build.gradle添加 google() 代码库,然后app的build.gradle引入依赖,官方给出的依赖如下:
//根目录的 build.gradle
repositories {
google()
...
}
//app的build.gradle
dependencies {
def lifecycle_version = "2.2.0"
def arch_version = "2.1.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// 只有Lifecycles (不带 ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// lifecycle注解处理器
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
// 替换 - 如果使用Java8,就用这个替换上面的lifecycle-compiler
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
//以下按需引入
// 可选 - 帮助实现Service的LifecycleOwner
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
// 可选 - ProcessLifecycleOwner给整个 app进程 提供一个lifecycle
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
// 可选 - ReactiveStreams support for LiveData
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
// 可选 - Test helpers for LiveData
testImplementation "androidx.arch.core:core-testing:$arch_version"
}
看着有很多,实际上如果只使用Lifecycle,只需要引入lifecycle-runtime即可。但通常都是和 ViewModel、 LiveData 配套使用的,所以lifecycle-viewmodel、lifecycle-livedata 一般也会引入。
另外,lifecycle-process是给整个app进程提供一个lifecycle,会面也会提到。
2.2.2 使用方法
Lifecycle的使用很简单:
- 1、生命周期拥有者 使用getLifecycle()获取Lifecycle实例,然后代用addObserve()添加观察者;
- 2、观察者实现LifecycleObserver,方法上使用OnLifecycleEvent注解关注对应生命周期,生命周期触发时就会执行对应方法;
2.2.2.1 基本使用
在Activity(或Fragment)中 一般用法如下:
public class LifecycleTestActivity extends AppCompatActivity {
private String TAG = "Lifecycle_Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_test);
//Lifecycle 生命周期
getLifecycle().addObserver(new MyObserver());
Log.i(TAG, "onCreate: ");
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "onResume: ");
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "onPause: ");
}
}
Activity(或Fragment)是生命周期的拥有者,通过getLifecycle()方法获取到生命周期Lifecycle对象,Lifecycle对象使用addObserver方法 给自己添加观察者,即MyObserver对象。当Lifecycle的生命周期发生变化时,MyObserver就可以感知到。
MyObserver是如何使用生命周期的呢?看下MyObserver的实现:
public class MyObserver implements LifecycleObserver {
private String TAG = "Lifecycle_Test";
@OnLifecycleEvent(value = Lifecycle.Event.ON_RESUME)
public void connect(){
Log.i(TAG, "connect: ");
}
@OnLifecycleEvent(value = Lifecycle.Event.ON_PAUSE)
public void disConnect(){
Log.i(TAG, "disConnect: ");
}
}
首先MyObserver实现了接口LifecycleObserver,LifecycleObserver用于标记一个类是生命周期观察者。
然后在connectListener()、disconnectListener()上 分别都加了@OnLifecycleEvent注解,且value分别是Lifecycle.Event.ON_RESUME、Lifecycle.Event.ON_PAUSE,这个效果就是:connectListener()会在ON_RESUME时执行,disconnectListener()会在ON_PAUSE时执行。
我们打开LifecycleTestActivity 然后退出,日志打印如下:
2020-11-09 17:25:40.601 4822-4822/com.hfy.androidlearning I/Lifecycle_Test: onCreate:
2020-11-09 17:25:40.605 4822-4822/com.hfy.androidlearning I/Lifecycle_Test: onResume:
2020-11-09 17:25:40.605 4822-4822/com.hfy.androidlearning I/Lifecycle_Test: connect:
2020-11-09 17:25:51.841 4822-4822/com.hfy.androidlearning I/Lifecycle_Test: disConnect:
2020-11-09 17:25:51.841 4822-4822/com.hfy.androidlearning I/Lifecycle_Test: onPause:
可见MyObserver的方法 确实是在对应关注的生命周期触发时调用。 当然注解中的value你也写成其它 你关注的任何一个生命周期,例如Lifecycle.Event.ON_DESTROY。
2.2.2.2 MVP架构中的使用
如果是 在MVP架构中,那么就可以把presenter作为观察者:
public class LifecycleTestActivity extends AppCompatActivity implements IView {
private String TAG = "Lifecycle_Test";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_test);
//Lifecycle 生命周期
// getLifecycle().addObserver(new MyObserver());
//MVP中使用Lifecycle
getLifecycle().addObserver(new MyPresenter(this));
Log.i(TAG</