Android LifeCycle详解
文章目录
- 1.1 LifeCycle的诞生
- 1.2 LifeCycIe的原理
- 1.3 在Activity中使用
- 1.4 使用LifecycleService解耦Service与组件
- 1.5 使用ProcessLifecycleOwner监听应用程序的生命周期
- ProcessLifecycIeOwner存在的意义
- ProcessLifecycIeOwner的具体使用方法
- 1.6 一些小Tips
1.1 LifeCycle的诞生
解耦是软件开发中永恒的话题。在Android应用程序开发中,解耦很大程度上表现为系统组件[1]的生命周期与普通组件[2]之间的解耦。普通组件在使用过程中通常需要依赖于系统组件的生命周期。有时候,我们不得不在系统组件的生命周期回调方法中,主动对普通组件进行调用或控制。因为普通组件无法主动获知系统组件的生命周期事件。
举个例子,我们经常需要在页面的onCreate()方法中对组件进行初始化,在onPause()方法中停止组件,而在页面的onDestroy()方法中对组件进行资源回收工作。这样的工作非常烦琐,会让页面与组件之间的耦合度变高。但这些工作又不得不做,因为这可能会引发内存泄漏。
我们希望我们对自定义组件的管理,不依赖于页面生命周期的回调方法。同时,在页面生命周期发生变化时,也能够及时收到通知。这在组件化和架构设计中显得尤为重要,如图2-1所示。
为此,Google提供了LifeCycle作为解决方案。LifeCycle可以帮助开发者创建可感知生命周期的组件。这样,组件便能够在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏发生的可能性。LifeCycle不只对Activity/Fragment有用,在Service和Application中也能大显身手。
1.2 LifeCycIe的原理
LifeCycle是如何解决这个问题的呢?Jetpack为我们提供了两个类:LifecycleOwner(被观察者)和LifecycleObserver(观察者)。即通过观察者模式,实现对页面生命周期的监听。
通过查看SupportActivity的源码,可以看到,在新版本的SDK包中,Activity已经默认实现了LifecycleOwner接口。LifecycleOwner接口中只有一个getLifecycle(LifecycleObserver observer)方法,LifecycleOwner正是通过该方法实现观察者模式的。源码示例如下。
从以上源码可知,SupportActivity已经替我们实现了被观察者应该实现的那一部分代码。因此,我们不需要再去实现这部分代码。当我们希望监听Activity的生命周期时,只需要实现观察者那一部分的代码,即让自定义组件实现LifecycleObserver接口即可。该接口没有接口方法,无须任何具体实现
除Activity之外,在新版本的SDK中,Fragment同样也默认实现了LifecycleOwner接口。因此,以上案例同样适用于Fragment。Fragment的源码如下所示。
1.3 在Activity中使用
示例如下:
public class MyLocationListener implements LifecycleObserver {public MyLocationListener(Context activity,OnLocationChangeListener changeListener) {}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)private void startGetLocation(){Log.i("MyLocationListener","OnResume");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)private void stopGetLocation(){Log.i("MyLocationListener","OnPause");}public interface OnLocationChangeListener{void onChange(double latitude,double longitude);}
}
在Activity
public class MainActivity extends AppCompatActivity {private MyLocationListener myLocationListener;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);myLocationListener=new MyLocationListener(this, new MyLocationListener.OnLocationChangeListener() {@Overridepublic void onChange(double latitude, double longitude) {}});getLifecycle().addObserver(myLocationListener);}
}
就这么简单!LifeCycle完美解决了组件对页面生命周期的依赖问题,使组件能够自己管理其生命周期,而无须在页面中对其进行管理。这无疑大大降低了代码的耦合度,提高了组件的复用程度,也杜绝了由于对页面生命周期管理的疏忽而引发的内存泄漏问题,这在项目工程量大的情况下是非常有帮助的。
1.4 使用LifecycleService解耦Service与组件
在上文中,我们介绍了如何利用LifeCycle来监听页面的生命周期,以达到解耦组件的目的。我们知道,拥有生命周期概念的组件除了Activity和Fragment,还有一个非常重要的组件是Service。为了便于对Service生命周期的监听,达到解耦Service与组件的目的,Android提供了一个名为LifecycleService的类。该类继承自Service,并实现了LifecycleOwner接口。与Activity/Fragment类似,它也提供了一个名为getLifecycle()的方法供我们使用。LifecycleService的源码如下所示
首先在build.gradle文件中加入
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
创建一个名为MyService的类,并让它继承自LifecycleService。由于LifecycleService是Service的直接子类,所以使用起来与普通Service没有差别。
import androidx.lifecycle.LifecycleService;public class MyService extends LifecycleService {private MyLifecycleObserver myLifecycleObserver;public MyService() {myLifecycleObserver = new MyLifecycleObserver();getLifecycle().addObserver(myLifecycleObserver);}
}
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;public class MyLifecycleObserver implements LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)private void startGetLocation(){Log.i("MyLocationListener","OnResume");}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)private void stopGetLocation(){Log.i("MyLocationListener","OnPause");}
}
1.5 使用ProcessLifecycleOwner监听应用程序的生命周期
ProcessLifecycIeOwner存在的意义
具有生命周期的系统组件除Activity、Fragment、Service外,还有Application。很多时候,我们会遇到这样的需求:我们想知道应用程序当前处在前台还是后台,或者当应用程序从后台回到前台时,我们能够得到通知。有不少方案能够实现该需求,但都不够好。在此之前,Google并没有为该需求提供官方解决方案,直到LifeCycle的出现。LifeCycle提供了一个名为ProcessLifecycleOwner的类,以方便我们知道整个应用程序的生命周期情况。
ProcessLifecycIeOwner的具体使用方法
首先,我们需要在app的build.gradle文件中添加相关依赖。
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
import com.example.jetpackdemo.LifeCycle.ApplicationObserver;
import com.example.jetpackdemo.LifeCycle.MyLifecycleObserver;public class MyApplication extends Application {@Overridepublic void onCreate() {super.onCreate();ProcessLifecycleOwner.get().getLifecycle().addObserver(new ApplicationObserver());}
}
import android.util.Log;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;public class ApplicationObserver implements LifecycleObserver {@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)private void onCreate(){Log.i("Application","OnCreate");}@OnLifecycleEvent(Lifecycle.Event.ON_START)private void onStart(){Log.i("Application","OnStart");}@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)private void onResume(){Log.i("Application","OnResume");}@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)private void onPause(){Log.i("Application","OnPause");}@OnLifecycleEvent(Lifecycle.Event.ON_STOP)private void onStop(){Log.i("Application","OnStop");}@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)private void onDestroy(){Log.i("Application","OnPause");}
}
通过以上示例可以看出,有了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。需要注意的是,这两个方法的调用会有一定的延后。这是因为系统需要为“屏幕旋转,由于配置发生变化而导致Activity重新创建”的情况预留一些时间。也就是说,系统需要保证当设备出现这种情况时,这两个事件不会被调用。因为当旋转屏幕时,你的应用程序并没有退到后台,它只是进入了横/竖屏模式而已。
1.6 一些小Tips
1、尝试复用LifecycleRegistry
首先,LifecycleRegistry 本身就是一个成熟的 Lifecycle 实现类,它被实例化在Activity和Fragment中使用,如果我们需要自定义LifecycleOwner 并实现接口需要返回一个Lifecycle实例,完全可以直接在自定义LifecycleOwner中new一个LifecycleRegistry成员并返回它(简而言之就是:直接拿来用即可)。
以下是Google官方文档:
LifecycleRegistry:
An implementation of Lifecycle that can handle multiple observers.
It is used by Fragments and Support Library Activities.
You can also directly use it if you have a custom LifecycleOwner.
2、注解和DefaultLifecycleObserver的取舍
其次,Google的Lifecycle库中提供了一个 DefaultLifecycleObserver 类,方便我们直接实现LifecycleObserver接口,相比较于文中demo所使用的注解方式,Google官方更推荐我们使用 DefaultLifecycleObserver 类,并声明
一旦Java 8成为Android的主流,注释将被弃用,所以介于DefaultLifecycleObserver和注解两者之间,更推荐使用 DefaultLifecycleObserver 。
Android LifeCycle详解相关推荐
- 【转】Android菜单详解——理解android中的Menu--不错
原文网址:http://www.cnblogs.com/qingblog/archive/2012/06/08/2541709.html 前言 今天看了pro android 3中menu这一章,对A ...
- Android菜单详解——理解android中的Menu
前言 今天看了pro android 3中menu这一章,对Android的整个menu体系有了进一步的了解,故整理下笔记与大家分享. PS:强烈推荐<Pro Android 3>,是我至 ...
- Android LayoutInflater详解
Android LayoutInflater详解 在实际开发中LayoutInflater这个类还是非常有用的,它的作用类 似于findViewById().不同点是LayoutInflater是用来 ...
- android Fragments详解
android Fragments详解一:概述 android Fragments详解二:创建Fragment 转载于:https://my.oschina.net/liangzhenghui/blo ...
- android WebView详解,常见漏洞详解和安全源码(下)
上篇博客主要分析了 WebView 的详细使用,这篇来分析 WebView 的常见漏洞和使用的坑. 上篇:android WebView详解,常见漏洞详解和安全源码(上) 转载请注明出处:http ...
- android WebView详解,常见漏洞详解和安全源码(上)
这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析. 由于博客内容长度,这次将分为上下两篇,上篇详解 WebView ...
- android子视图无菜单,Android 菜单详解
Android中菜单分为三种,选项菜单(OptionMenu),上下文菜单(ContextMenu),子菜单(SubMenu) 选项菜单 可以通过两种办法增加选项菜单,一是在menu.xml中添加,该 ...
- Android StateFlow详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121913352 本文出自[赵彦军的博客] 文章目录 系列文章 一.冷流还是热流 S ...
- Android SharedFlow详解
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/121911675 本文出自[赵彦军的博客] 文章目录 系列文章 什么是SharedF ...
最新文章
- 玩纸牌游戏计算机教案,小班数学好玩的扑克牌教案
- 孙庆新:做产品,感觉从何而来
- const那些事-初始化
- Git:改变世界的一次代码提交
- linux下配置钉钉内网穿透_4G工业路由器内嵌花生壳PHTunnel,为工业物联网提供智能内网穿透...
- [转]WF事件驱动(4) -持久化
- cognos transformer 建一个85w数据的cube所用的时间,接优化
- 计算机系毕业论文绪论,本科毕业论文绪论范文
- Python路飞学城老男孩内部书籍,Python全栈开发实战pdf
- STM32F103C8T6红外遥控解码
- 2016最新php授权验证系统v2.1,2016PHP受权验证系统V2.1完整版,域名+IP双重验证 一键升级受权系统 完美无错...
- Java面试题笔试题汇总
- WPS使用宏操作——减少重复性操作,提高效率
- 何小黑的2019年秋招面经~
- 面试,这些问题一定要问清楚!
- 层次分析法(AHP)基础概念整理+步骤总结
- 【论文阅读】PGM-index
- 插板法、捆绑法、插空法
- SpringBoot的easyui实现导入和导出功能到excel
- linux中搜索文件内容关键字--转载哈