前言
什么是生命周期感知组件?
生命周期感知型组件可执行操作来响应另一个组件(如 Activity 和 Fragment)的生命周期状态的变化。这些组件有助于您写出更有条理且往往更精简的代码,这样的代码更易于维护。
Lifecycle是什么?
Lifecycle 是一个类,用于存储有关组件(如 Activity 或 Fragment)的生命周期状态的信息,并允许其他对象观察此状态。
它所解决的痛点问题是什么?
在 Android 框架中定义的大多数应用组件都存在生命周期。生命周期由操作系统或进程中运行的框架代码管理。它们是 Android 工作原理的核心,应用必须遵循它们。如果不这样做,可能会引发内存泄漏甚至应用崩溃。
【本系列文章(JAVA/KOTLIN)演示案例均存储在github存储库ArchitecturalComponentExample中】
使用Lifecycle的意义
说起Activity生命周期,不难想到Application有个方法registerActivityLifecycleCallbacks()
可以注册生命周期回调, 且在Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
时的Activity也扩展了这个方法,获取activity生命周期状态:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle bundle) { Log.i("loglog", "onActivityCreated"); }
@Override public void onActivityStarted(@NonNull Activity activity) { Log.i("loglog", "onActivityStarted"); }
@Override public void onActivityResumed(@NonNull Activity activity) { Log.i("loglog", "onActivityResumed"); }
@Override public void onActivityPaused(@NonNull Activity activity) { Log.i("loglog", "onActivityPaused"); }
@Override public void onActivityStopped(@NonNull Activity activity) { Log.i("loglog", "onActivityStopped"); }
@Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle bundle) { Log.i("loglog", "onActivitySaveInstanceState"); }
@Override public void onActivityDestroyed(@NonNull Activity activity) { Log.i("loglog", "onActivityDestroyed"); } });
|
同样的,我们也可以在Activity中单纯使用生命周期回调onCreate()
、onResume()
等来实现生命周期监听。
具体案例参考官方文档
我们不难发现这样写存在这样一些问题:
- 生命周期管理集中,且并非所有生命周期回调我们都要用
- 若同一生命周期回调中要做多个功能,同一个回调方法中代码量将会很大,这将带来巨大的维护成本
- 无法保证组件会在 Activity 或 Fragment 停止之前启动。在我们需要执行长时间运行的操作(如 onStart() 中的某种配置检查)时尤其如此。这可能会导致出现一种竞态条件,在这种条件下,onStop() 方法会在 onStart() 之前结束,这使得组件留存的时间比所需的时间要长。
Lifecycle 可以为你的每一个功能提供独立的生命周期观察者,做到功能代码与界面(Activity/Fragment)更小的耦合,且每一个功能的生命周期观察者都可以被复用,功能组件的抽离也能为你的程序带来更强大的扩展性。
使用Lifecycle
引入依赖
文档编写时,稳定依赖版本为2.2.0
,下一候选预览版为2.3.0-rc01
,引入时请检查官方文档推荐版本,以当前稳定版为主要选择。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| dependencies { def lifecycle_version = "2.3.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 和 LiveData支持) implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
// 保存ViewModel的状态模块 implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"
// 注解处理器 annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // 另外——如果使用Java8,使用下面的代码代替lifecycle-compiler implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// 可选——在服务中实现LifecycleOwner的助手 implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
// 可选- ProcessLifecycleOwner为整个应用程序过程提供一个生命周期 implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
// 可选- ReactiveStreams支持LiveData implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"
// 可选的- LiveData的测试助手 testImplementation "androidx.arch.core:core-testing:$arch_version" }
|
以上依赖库并非所有内容均需要引入,请根据实际需求引入对应依赖。
例如,你单纯的想使用Lifecycle的生命周期管理能力,你可以这样引入依赖:
1 2 3 4 5 6 7 8 9
| dependencies { def lifecycle_version = "2.3.0"
// 单纯生命周期组件 implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
// 负责进程(应用)的生命周期 implementation 'androidx.lifecycle:lifecycle-process:$lifecycle_version' }
|
LifecycleObserver
编写你的LifecycleObserver 观察者,并将其添加到界面组件的LifecycleOwner观察队列(集合)中
,即可完成对界面组件生命周期的观察,你可以在你的LifecycleObserver 定义你感兴趣的生命周期事件,例如你需要控制相机在亮/息屏时开启或停止,你可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class CameraLifecycleObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE) public void initCamera(){ Log.i("loglog", "ON_CREATE 初始化相机"); }
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void openCamera() { Log.i("loglog", "ON_RESUME 打开相机"); }
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void closeCamera() { Log.i("loglog", "ON_PAUSE 关闭相机"); }
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy(){ Log.i("loglog", "ON_DESTROY 销毁资源"); } }
|
当然,若你还想利用其他生命周期,或者主动获取组件的生命周期,你或可以将生命周期组件传入CameraLifecycleObserver组件中,通过其获取当前生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class CameraLifecycleObserver implements LifecycleObserver {
private Lifecycle mLifecycle = null; public CameraLifecycleObserver(Lifecycle lifecycle){ mLifecycle = lifecycle; }
@OnLifecycleEvent(Lifecycle.Event.ON_ANY) public void onAny(){ Lifecycle.State currentState = mLifecycle.getCurrentState(); boolean hasStarted = currentState.isAtLeast(Lifecycle.State.STARTED); } }
|
组件实现LifecycleOwner
完成了观察者的编写,我们可以将观察者的实例传递给LifecycleOwner,而关于Lifecycleowner你可能存在以下两种情况:
- 你使用了Androidx支持库,且版本
>=26.1.0
, Fragment 和 Activity 已实现 LifecycleOwner 接口,此处主要指继承自ComponentActivity
及其子类的Activity和继承自androidx.fragment.app.Fragment
的Fragment。
- 其他情况,你需要自行实现LifecycleOwner ,并重写
getLifecycle()
方法,并手动分发你需要的生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class MyActivity extends Activity implements LifecycleOwner { private LifecycleRegistry lifecycleRegistry; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); lifecycleRegistry = new LifecycleRegistry(this); lifecycleRegistry.markState(Lifecycle.State.CREATED); } @Override public void onStart() { super.onStart(); lifecycleRegistry.markState(Lifecycle.State.STARTED); } @NonNull @Override public Lifecycle getLifecycle() { return lifecycleRegistry; } }
|
将观察者交给LifecycleOwner
当你拥有LifecycleOwner对象后,你就可以将你实现的观察者LifecycleObserver 交给它了,当有生命周期变化事件发生,LifecycleObserver将会通知你的LifecycleOwner。
1
| getLifecycle().addObserver(new CameraLifecycleObserver(...params));
|
让我们来看一下其执行结果:
1 2 3 4 5 6 7 8 9
| I/loglog: ON_CREATE 初始化相机 I/loglog: onActivityStarted I/loglog: onActivityResumed I/loglog: ON_RESUME 打开相机 I/loglog: ON_PAUSE 关闭相机 I/loglog: onActivityPaused I/loglog: onActivityStopped I/loglog: ON_DESTROY 销毁资源 I/loglog: onActivityDestroyed
|
为进程添加生命周期事件
如果你想监听应用前后台变化,你可以看下此小节。
以往的,观察应用是否前台,你可以这样做:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public boolean inAppOnForeground(Context context) { try { ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE); String packageName = context.getPackageName(); if (activityManager != null) { List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses(); if (appProcesses == null) { return false; } for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { if (packageName.equals(appProcess.processName) && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { return true; } } } } catch (Exception e) { e.printStackTrace(); } return false; }
|
这样你只能知道应用是否前台,但无法知道它什么时候进入前台,什么时候进入后台,如果你恰好需要知道应用何时进入后台执行某项工作,这样做可能并不适合。当然你也可以通过Application.registerActivityLifecycleCallbacks()监听activity的启动和退出,为其启动和退出计数,当退出时计数为0则可视作应用后台,当启动时计数为1则可视做应用前台,emmmm,想想我就觉得工作量挺大~
让我们看看使用Lifecycle如何简单做到这件事情吧(需引入依赖androidx.lifecycle:lifecycle-process:$last_version):
- 编写生命周期观察者
- 为你的Application添加生命周期观察者
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class ProcessLifecycleObserver implements LifecycleObserver { private boolean isForeground = false;
@OnLifecycleEvent(Lifecycle.Event.ON_START) public void onForeground() { Log.i("loglog", "onForeground: ON_START"); isForeground = true; }
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) public void onBackground() { Log.i("loglog", "onBackground: ON_STOP"); isForeground = false; } public boolean isForeground() { return isForeground; }
}
public class MyApplication extends Application {
private ProcessLifecycleObserver observer;
@Override public void onCreate() { super.onCreate();
observer = new ProcessLifecycleObserver(); ProcessLifecycleOwner.get().getLifecycle().addObserver(observer); } public boolean isForeground() { return observer.isForeground(); } }
|
这样就简单的完成了应用前后台切换的监听,以及前后台状态的查询了~
如需了解生命周期感知组建的最佳做法,请点击 官方文档 获得详细内容
关于Lifecycle 与LiveData等jetpack组件配合使用,将在架构组件基础使用系列完结后一并编写介绍,在此之前,请参考官方文档