前言
前面几篇文章都是为了Jetpack 打基础,本篇从Lifecycle开始将正式进入Jetpack 各个组件的分析。
通过本篇文章你将了解到:
1、为什么需要Lifecycle?
2、Lifecycle 如何使用?
3、Lifecycle 如何感知生命周期
4、Lifecycle 内存泄漏?
5、总结
1、为什么需要Lifecycle?
生命周期的起始
Android 中常见的拥有生命周期的组件如Activity、Fragment、Service等,其中Activity、Fragment最为常见,而Fragment的生命周期依托于Activity,因此掌握了Activity的生命周期,其它不在话下。
Activity 生命周期跌宕起伏的故事,请移步:
Android Activity 生命周期详解及监听
生命周期的运用
青铜选手
举个简单的例子:当进入Activity 时(获取焦点)需要网络请求,当Activity 退出时(失去焦点)停止网络请求,最简单的做法如下:
@Override
protected void onResume() {
super.onResume();
NetRequest.startRequest();
}
@Override
protected void onPause() {
super.onPause();
NetRequest.stopRequest();
}
复制代码
重写onResume()方法,当该方法被调用时,说明Activity获取了焦点,页面即将展示,此时可以进行网络请求拉取数据。
重写onPause()方法,当该方法被调用时,说明Activity 失去了焦点,此时没必要再请求网络了。
看似没啥问题,但仔细想想:比如在播放视频的时候,也需要在onResume()方法里播放,在onPause()方法里暂停,再比如数据库操作等,这个时候onResume()、onPause()里就叠放了许多代码,使得Activity 变得很臃肿。
白银选手
你说没关系,我有MVP 架构,可以用Presenter 来封装这些业务逻辑。
声明Presenter类:LifecyclePresenter。
public class LifecyclePresenter implements ILifecycle{
@Override
public void onResume() {
NetRequest.startRequest();
}
@Override
public void onPause() {
NetRequest.stopRequest();
}
}
复制代码
该类实现了接口:ILifecycle,而此接口声明的方法与Activity 生命周期契合:
interface ILifecycle {
void onCreate();
void onStart();
void onResume();
void onPause();
void onStop();
void onDestroy();
}
复制代码
好了,最后在Activity 里监听生命周期的变化,进而调用LifecyclePresenter 不同方法:
@Override
protected void onResume() {
super.onResume();
lifecyclePresenter.onResume();
}
@Override
protected void onPause() {
super.onPause();
lifecyclePresenter.onPause();
}
复制代码
如此一来,以后有其它的业务逻辑,只需要在LifecyclePresenter 对应的方法里添加即可,达成了给Activity 减负的效果。
黄金选手
虽然Activity 生命周期各个方法里只新增了一行代码,但是考虑到UI 和逻辑的分离,最好是两者不产生耦合。比如在分工的时候,有些同学负责UI,那么他可能就不会关心什么时候开始/结束网络请求,这些由负责具体业务逻辑的同学来编写。该怎么来实现呢?
还记得在分析Activity生命周期时有说过:
Activity 提供了registerActivityLifecycleCallbacks(callback)方法,当Activity生命周期发生变动时就会调用该方法。因此咱们可以在此监听生命周期的变动,然后调用相应的业务代码:
public class LifecycleHelper {
@RequiresApi(api = Build.VERSION_CODES.Q)
public static void bindLifecycle(Activity activity, ILifecycle iLifecycle) {
if (activity == null)
return;
activity.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityResumed(@NonNull Activity activity) {
if (iLifecycle != null)
iLifecycle.onResume();
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
if (iLifecycle != null)
iLifecycle.onPause();
}
});
}
}
复制代码
传入的Activity 即为想要监听生命周期的Activity。
public class LifecyclePresenterV2 {
@RequiresApi(api = Build.VERSION_CODES.Q)
public LifecyclePresenterV2(Activity activity) {
LifecycleHelper.bindLifecycle(activity, new ILifecycle() {
@Override
public void onResume() {
NetRequest.startRequest();
}
@Override
public void onPause() {
NetRequest.stopRequest();
}
});
}
}
复制代码
改造Presenter为:LifecyclePresenterV2。
此时,Activity 里只需要调用:
//this 表示当前需要监听的Activity
LifecyclePresenterV2 lifecyclePresenterV2 = new LifecyclePresenterV2(this);
复制代码
可以看出:
Activity 里无需再重写各个生命周期的回调方法,仅仅只需要一行代码,即可将这些逻辑放到单独的业务层处理,生命周期和具体业务绑定,看业务的需求想怎么和生命周期联动就怎么来。
后续若是换了Activity,那么逻辑层的业务也无需变动。
似乎万事大吉了?非也,仔细看registerActivityLifecycleCallbacks()方法调用有版本限制:@RequiresApi(api = Build.VERSION_CODES.Q)
意思就是该API 必须是Android 10(29)以上才能调用,这局限性可大了。
Lifecycle 的引入
从上面的分析我们可以感知到,生命周期和业务的联动场景挺丰富的,也着实需要一套工具来帮助我们简化联动过程。
Google说要有Lifecycle,于是便有了Lifecycle。
开宗明义:Lifecycle 源码并不复杂,主要就是做了三件事:
1、提供给外界监听感兴趣的生命周期里的某个阶段(onResume、onPause、onDestroy等)的接口,外界此时化身为观察者。
2、在某个地方监听Activity生命周期,此时Activity为被观察者。
3、将生命周期告知给观察者。
2、Lifecycle 如何使用?
添加观察者
从Lifecycle 三件事可知,外界想要监听生命周期变化,仅仅只需要添加观察接口,在接口的回调方法里处理对应生命周期即可。
有两种不同的方式:
1、注解方式处理观察结果
Lifecycle 以前的版本为了少重写接口里的方法,使用了注解来简化观察者。
//注解的实现方式
class MyObserver7 implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause() {
Log.d(TAG, "onPause");
}
}
复制代码
此处只关注onPause,若是还想监测其它状态变化,只需要添加对应状态的注解即可。
而后在Activity 里监听:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle);
getLifecycle().addObserver(new MyObserver7());
}
复制代码
当Activity 失去焦点后就会调用MyObserver7里的onPause()方法。
可以看出,在Activity里只需要添加观察者即可。
2、接口方式处理观察结果
Lifecycle 新版本废弃了注解观察方式,使用了接口来代替,若是你使用了Java8或者开启了Java8 特性,建议使用接口方式。
//Java8 方式
class MyObserver8 implements DefaultLifecycleObserver {
@Override
public void onPause(LifecycleOwner owner) {
Log.d(TAG, "pause");
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle);
getLifecycle().addObserver(new MyObserver8());
}
复制代码
可以看出,实现了DefaultLifecycleObserver 接口,该接口继承了FullLifecycleObserver 接口。
interface FullLifecycleObserver extends LifecycleObserver {
void onCreate(LifecycleOwner owner);
void onStart(LifecycleOwner owner);
void onResume(LifecycleOwner owner);
void onPause(LifecycleOwner owner);
void onStop(LifecycleOwner owner);
void onDestroy(LifecycleOwner owner);
}
复制代码
而DefaultLifecycleObserver 接口默认实现了FullLifecycleObserver全部的方法
@Override
default void onCreate(@NonNull LifecycleOwner owner) {
}
....
复制代码
可以看出使用了Java8 的新特性:default 修饰接口方法。
因此当我们实现了DefaultLifecycleObserver接口时,仅仅只需要重写关注的状态对应的接口即可。
3、Lifecycle 如何感知生命周期
综上所述,通过Lifecycle 可以很方便地感知Activity生命周期的变化,前面部分咱们也是一步步分析该怎么封装生命周期,很遗憾遇到了registerActivityLifecycleCallbacks 版本限制的问题,接下来探究Lifecycle究竟是怎么做到绕开限制的。
第一步:注册观察者
LifecycleRegistry
不管是接口还是注解方式都使用了getLifecycle(),该方法返回Lifecycle 对象,而Lifecycle是抽象类,getLifecycle()返回的是Lifecycle 的子类:LifecycleRegistry 的对象。
#ComponentActivity.java
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
复制代码
当自定义的Activity 继承自AppCompatActivity时,而ComponentActivity 是 AppCompatActivity 的父类,因此自定义的Activity 调用getLifecycle()时返回的即是mLifecycleRegistry 对象。
而LifecycleRegistry里的mLifecycleOwner对象即是自定义的Activity 本身(弱引用)。
addObserver()
#LifecycleRegistry.java
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
Lifecycle.State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
//传入observer,构造ObserverWithState
LifecycleRegistry.ObserverWithState statefulObserver = new LifecycleRegistry.ObserverWithState(observer, initialState);
//将ObserverWithState 加入到map 里
LifecycleRegistry.ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
...
}
复制代码
关键之处在于ObserverWithState:
#LifecycleRegistry.java
static class ObserverWithState {
//生命周期状态
Lifecycle.State mState;
//观察者
LifecycleEventObserver mLifecycleObserver;
ObserverWithState(LifecycleObserver observer, Lifecycle.State initialState) {
//封装观察者
mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
mState = initialState;
}
void dispatchEvent(LifecycleOwner owner, Lifecycle.Event event) {
//分发事件,将event转为state
Lifecycle.State newState = event.getTargetState();
mState = min(mState, newState);
mLifecycleObserver.onStateChanged(owner, event);
mState = newState;
}
}
复制代码
再看Lifecycling.lifecycleEventObserver:
#Lifecycling.java
static LifecycleEventObserver lifecycleEventObserver(Object object) {
//接口方式
boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
...
if (isFullLifecycleObserver) {
//如果观察者是接口方式,直接返回
return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
}
//处理注解,将注解记录下来,下次直接从map里取
final Class<?> klass = object.getClass();
int type = getObserverConstructorType(klass);
...
return new ReflectiveGenericLifecycleObserver(object);
}
复制代码
addObserver()的重点是将Observer经过一些列封装后添加到Map里。
明显地我们会想到:当生命周期变更后,将会从Map里取出观察者,并通知它。
第二步:生命周期变更-通知观察者
Android10(含) 以上处理方式
了解Lifecycle 如何通知观察者,最好的方法莫过于通过断点查看其调用堆栈。
以接口处理方式为例,当观察者被调用时,其调用栈如下: