Android架构之LifeCycle组件
LifeCycle的简介
LifeCycle可以帮助开发者创建可感知生命周期的组件。这样,组件便能够在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏发生的可能性
为什么要引入LifeCycle
举个例子,我们经常需要在页面的onCreate()方法中对组件进行初始化,在onPause()方法中停止组件,而在页面的onDestroy()方法中对组件进行资源回收工作。这样的工作非常烦琐,会让页面与组件之间的耦合度变高。但这些工作又不得不做,因为这可能会引发内存泄漏。
假设有这样一个常见的需求:在用户打开某个页面时,获取用户当前的地理位置。面对该需求,我们通常会这样写代码。
class MainActivity extends AppCompatActivity {
public void onCreate(...) {
//初始化位置管理器
iniLocationManager();
}
public void onResume(){
//开始获取用户的地理位置
startGetLocation();
}
public void onPause() {
//停止获取用户的地理位置
stopGetLocation();
}
public void onDestroy() {
//销毁位置管理器
delGetLocation();
}
}
每次都是在onCreate方法里面去进行注册,然后再onDestroy方法进行销毁,这样的代码毫无意义。 当前我们写一个BaseActivity对所需要的组件进行初始化和销毁,然后使其它的Activity继承自BaseActivity, 可以减少很多不必要的代码。
但是还有没有更好的办法呢? 当然是有的,那就是LifeCycle可以解决这个问题,LifeCycle不只对Activity/Fragment有用,在Service和Application中也能大显身手.接下来让我们来看看LifeCycle是如何解决的?
LifeCyCle的原理
Jetpack为我们提供了两个类: LifecycleOwner(被观察者)和LifecycleObserver(观察者). 即通过观察者模式,实现对页面生命周期的监听
可以通过查看SupportActivity的源码,Activity已经默认实现了LifecycleOwner接口,并且接口中只有一个getLifeCycle(LifecycleObserver observer)方法,LifecycleOwner正是通过该方法实现观察者模式的。源码示例如下
从以上源码可知,SupporyActiviry已经替我们实现了被观察者应该实现的那一部分代码。当我们希望监听Activity的生命周期时,只需要实现观察者那一部分的代码,即让自定义组件实现LifecycleObserver接口即可。该接口没有接口方法。
LifeCycle基本使用
- 编写一个名为MyLocationListener的类。该类就是我们自定义组件,我们需要让组件实现LifecycleObserver接口,与获取地理位置相关的代码再该类中完成
- 对于组件中那些需要再页面生命周期发送变化时得到通知的方法,我们需要在这些方法上使用@OnLifecycleEvent(Lifecycle.Event.ON_xxx)注解进行标识。这样,当页面生命周期发生变化时,这些被注解标识过的方法会被自动调用。
MyLocationListener 代码如下
public class MyLocationListener implements LifecycleObserver {
public MyLocationListener(Activity context, OnLocationChangeListener listener) {
//初始化操作
iniLocationManager();
}
private void iniLocationManager() {
}
//当Activity执行onResume()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
private void startGetLocation(){
Log.e("true","onResume"+"被调用了");
}
//当Activity执行onPause()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
private void stopGetLocation(){
Log.e("true","onPause"+"被调用了");
}
//当Activity执行onDestroy()方法时,该方法会被自动调用
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private void delGetLocation(){
Log.e("true","onDestroy"+"被调用了");
}
//当地理位置发送改变时,通过该接口通知调用者
public interface OnLocationChangeListener{
void onChanged(double latitude,double longitude);
}
}
主MainActivity
在MainActivity中,只需要引用MyLocationListener即可,不用再关心Activity生命周期变化对该组件所带来的影响。生命周期的管理完全交给MyLocationListener内部自行处理。在Activity中要做的只是通过getLifecycle().addObserver()方法,将观察者与被观察者绑定起来,代码如下:
public class MainActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myLocationListener = new MyLocationListener(this, new MyLocationListener.OnLocationChangeListener() {
@Override
public void onChanged(double latitude, double longitude) {
//展示收到的位置信息
}
});
//将观察者与被观察者绑定
getLifecycle().addObserver(myLocationListener);
}
}
运行结果如下:
是不是很简单呢? LifeCycle完美解决了组件对页面生命周期的依赖问题。
除Activity之外,在新版本的SDK中,Fragment同样也默认实现了LifecycleOwner接口。因此,以上案例同样适用于Fragment。Fragment的源码如下所示。
LifeCycIeService基本介绍
众所周知,拥有生命周期概念的组件除了Activity和Fragment,还有一个非常重要的组件是Service,为了便于对Service生命周期的监听,Android提供了一个名为 LifecycleService的类,也实现了LifecycleOwner接口.
LifecycleService的源码如下所示
LifecycleService的使用
1.首先,在app的build.gradle文件中添加相关依赖
dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
}
2.创建一个名为MyService的类,继承LifecycleService.由于LifecycleService是Service的直接子类,所以使用起来与普通Service没有差别
public class MyService extends LifecycleService {
private MyServiceObserver myServiceObserver;
public MyService( ) {
myServiceObserver = new MyServiceObserver();
//将观察者与被观察者绑定
getLifecycle().addObserver(myServiceObserver);
}
}
3.创建MyServiceObserver类,该类实现LifecycleObserver接口,使用@OnLifecycleEvent注解对那些你希望能够在Service生命周期发生变化时得到同步调用的方法进行标识。
public class MyServiceObserver implements LifecycleObserver {
//当Service的onCreate()方法被调用时,该方法会被调用
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
private void startGetLocation(){
Log.e("service","Service中的oncreate方法执行了");
}
//当Service的onDestroy()方法被调用时,该方法会被调用
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private void stopGetLocation(){
Log.e("service","Service中的onDestroy方法执行了");
}
}
4.在页面中利用两个Button,控制Service的 启动和停止,测试我们的代码
Button startBtn = findViewById(R.id.startService);
Button stopBtn = findViewById(R.id.stopService);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//启动服务
Intent intent = new Intent(MainActivity.this, MyService.class);
startService(intent);
}
});
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//停止服务
Intent intent = new Intent(MainActivity.this, MyService.class);
stopService(intent);
}
});
5.通过LogCat中的日志可以看到,随着Service生命周期的变化,MyServiceObserver中带有@OnLifecycleEvent注解的方法被自动调用.
6.千万别忘记了,需要在清单文件中(manifest)注册MyService
<application
<service android:name=".lifecycle.MyService"/>
</application>
通过以上示例可以看出,当Service的生命周期发生变化时,不再需要主动对组件进行通知,组件能够在其内部自行管理好生命周期所带来的变化。LifecycleService很好地实现了组件与Service之间的解耦。
使用ProcessLifecycleOwner监听应用程序的生命周期
ProcessLifecycleOwner存在的意义
具有生命周期的系统组件除Activity、Fragment、Service外,还有Application。很多时候,我们会遇到这样的需求:我们想知道应用程序当前处在前台还是后台,或者当应用程序从后台回到前台时,我们能够得到通知。LifeCycle提供了一个名为ProcessLifecycleOwner的类,以方便我们知道整个应用程序的生命周期情况。
ProcessLifecycleOwner的具体使用
1.首先,在app的build.gradle文件中添加相关依赖
dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
}
2.ProcessLifecycleOwner的使用方式与Activity、Fragment和Service是类似的,其本质也是观察者模式。由于我们要观察的是整个应用程序,因此,需要在Application中进行相关代码的编写。
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle()
.addObserver(new ApplicationObserver());
}
}
3.定义一个名为ApplicationObserver的类,让该类实现LifecycleObserver接口,以负责对应用程序生命周期的监听
public class ApplicationObserver implements LifecycleObserver {
//在应用程序的整个生命周期中只会被调用一次
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate(){
Log.e("application","Application onCreate方法执行了");
}
//在应用程序在前台出现时被调用
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart(){
Log.e("application","Application onStart方法执行了");
}
//在应用程序在前台出现时被调用
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume(){
Log.e("application","Application onResume方法执行了");
}
//在应用程序退出到后台时被调用
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause(){
Log.e("application","Application onPause方法执行了");
}
//在应用程序退出到后台时被调用
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop(){
Log.e("application","Application onStop方法执行了");
}
//永远不会被调用,系统不会分发调用ON_DESTROY事件
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy(){
Log.e("application","Application onDestroy方法执行了");
}
}
运行如下
通过以上示例可以看出,有了ProcessLifecycleOwner,我们可以很轻松地获取应用程序何时退到后台,何时进入前台,进而执行一些业务操作。使用起来非常简单,并且不会给项目增加任何的耦合度, 但有以下几点需要注意:
- ProcessLifecycleOwner是针对整个应用程序的监听,与Activity数量无关,你有一个Activity或多个Activity,对ProcessLifecycleOwner来说是没有区别的。
- Lifecycle.Event.ON_CREATE只会被调用一次,而Lifecycle.Event.ON_DESTROY永远不会被调用。
- 当应用程序从后台回到前台,或者应用程序被首次打开时,会依次调用Lifecycle.Event.ON_START和Lifecycle.Event.ON_RESUME。
- 当应用程序从前台退到后台(用户按下Home键或任务菜单键),会依次调用Lifecycle.Event.ON_PAUSE和Lifecycle.Event.ON_STOP
自定义 LifecycleOwner
Support Library 26.1.0 及更高版本中的 Fragment 和 Activity 已实现 LifecycleOwner 接口。
Support Library 26.1.0以下可以自定义LifecleOwner;
Support Library 26.1.0 及更高版本自定义LifecycleOwner会报错,亲测。
这里就拿Activity来举例吧,当我们想自定义LifecycleOwner,我们可以使用LifecycleRegistry类,但需要将事件转发到该类。
什么叫将事件转发到该类呢?
- 如果是自定义的LifecycleOwner,想要实现对某个生命周期进行监听的话,需要使用lifecycleRegistry.markState(Lifecycle.State.xxxx);加入到监听队伍中.
- 比如说,我想对Activity中的onStart()方法进行监听,那么就需要将onStart()方法加入到监听队伍中, lifecycleRegistry.markState(Lifecycle.State.STARTED);
- 上面不是已经说明,LifecycleOwner必须需要实现一个getLifecycle()方法,改方法需要返回一个Lifecycle类型的值,也就是我们创建的lifecycleRegistry
具体代码如下
public class MainActivity extends AppCompatActivity implements LifecycleOwner {
private MyLocationListener myLocationListener;
private LifecycleRegistry lifecycleRegistry;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.markState(Lifecycle.State.CREATED);
myLocationListener = new MyLocationListener(this, new MyLocationListener.OnLocationChangeListener() {
@Override
public void onChanged(double latitude, double longitude) {
//展示收到的位置信息
}
});
//将观察者与被观察者绑定
getLifecycle().addObserver(myLocationListener);
}
@Override
protected void onResume() {
super.onResume();
lifecycleRegistry.markState(Lifecycle.State.RESUMED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
MyLocationListener类上面有这里就不在给出了.
总结
所有具体生命周期的组件都能够使用LifeCycle.并且有了LifeCycle之后,在自定义组件内部便可以管理好其生命周期,不再需要担心组件的内层泄露等问题了,组件使用起来也更加方便和安全.