Lifecycle诞生的背景
在 Android 应用程序的开发过程,我们会经常遇到这样一个需求,一个第三方或系统组件需要在Activity/Fragment的onCreate()方法中初始化,在onPause()方法中停止组件,在onDestroy()中对组件进行资源回收。这样的工作非常繁琐,会让组件与页面的耦合度增高,但是这些繁琐的工作却又不得不做,否则可能会造成内存泄露。
我们希望我们对自定义的组件的管理,不依赖与页面的生命周期的回调方法,同时,在页面的生命周期发生变化时,也能及时收到通知。为此Google提供了Lifecycle作为解决方案。
什么是Lifecycle
Lifecycle 可以用于构建生命周期感知型组件,这些组件可以根据 Activity 或 Fragment 的当前生命周期状态调整行为。
Lifecycle的作用与意义
Lifecycle可以帮助开发者创建可感知生命周期的组件。这样,组件就可以在其内部管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄露的发生
需要注意的是,LifeCycle不仅只对Activity/Fragment有用,在Service和Application中同样可以使用。
Lifecycle使用示例
使用Lifecycle监听Activity/Fragment的生命周期
接下来我们以一个案例来演示Lifecycle是如何使用的。
假设有这样一个常见的需求:在用户打开某个页面时,获取用户当前的地理位置。用户离开该页面后,则停止获取用户地理位置。面对这样的需求,我们通常会这么写
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 初始化任务管理器
initLocationManager();
}
@Override
protected void onStart() {
super.onStart();
// 获取用户位置
getUserLocation();
}
@Override
protected void onPause() {
super.onPause();
// 停止获取用户位置
stopGetLocation();
}
@Override
protected void onDestroy() {
super.onDestroy();
// 释放任务管理器
releaseLocationManager();
}
}
从上述代码可以看出,获取地理位置这个需求的实现,和页面的生命周期息息相关。如果我们希望将获得地理位置这一功能独立成一个组件,那么我们不得不在页面生命周期各个回调方法中,对组件进行通知,只有这样组件才能感知到页面的生命周期变化(有经验的开发一定会注意到,这就是早期MVP架构中Presenter感知页面生命周期的做法)。
面对这个问题,接下来我们就来看看,LifeCycle是如何处理的。
在使用 Lifecycle 之前我们需要在应用或模块的build.gradle
中添加lifecycle的依赖项
lifecycle-extensions 目前已经弃用。Google为我们提供了,可供自由选择的lifecycle组件
dependencies {
def lifecycle_version = "2.3.1"
// Lifecycles only (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
}
我们为位置管理器定义一个类LocationObserver的类,LocationObserver需要实现LifecycleObserver接口。如果我们需要得知页面的生命周期,只需要定义一个@OnLifecycleEvent(Lifecycle.Event.ON_XXX)标签即可,当页面的生命周期发生变化时,这些被标识的方法会自定被调用。如下所示:
//1. 自定义的LifecycleObserver观察者,用注解声明每个方法观察的宿主的状态
class LocationObserver extends LifecycleObserver{
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart(@NotNull LifecycleOwner owner){
//开启定位
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop(@NotNull LifecycleOwner owner){
//停止定位
}
}
在Activity/Fragment中引用LocationObserver,并同过getLifecycle().addObserver(observer)方法将观察者与被观察者绑定起来,这样LocationObserver就能感知到Activity/Fragment的生命周期变化。如下所示:
//2. 注册观察者,观察宿主生命周期状态变化
class MyActivity extends AppCompactActivity{
public void onCreate(Bundle bundle){
MyLifecycleObserver observer =new MyLifecycleObserver();
getLifecycle().addObserver(observer);
}
}
//2. 注册观察者,观察宿主生命周期状态变化
class MyFragment extends Fragment{
public void onCreate(Bundle bundle){
MyLifecycleObserver observer =new MyLifecycleObserver();
getLifecycle().addObserver(observer);
}
}
除了继承LifecycleObserver
运用注解的形式来实现宿主生命周期的监听,Lifecycle
组件中还提供了LifecycleEventObserver
来监听宿主的生命周期。
public class LocationObserver implements LifecycleEventObserver {
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
//需要自行判断event是onstart, 还是onstop
}
}
如果你的项目使用了Java8,那么你还可以使用DefaultLifecycleObserver
来监听宿主的生命周期。
使用DefaultLifecycleObserver
之前,你还需要在build.gradle
中额外引入以下依赖
dependencies {
def lifecycle_version = "2.3.1"
...//省略其它依赖
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
}
然后实现DefaultLifecycleObserver
接口,根据需要实现里面的方法即可。
public class LocationObserver implements DefaultLifecycleObserver {
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
}
}
需要额外注意的是,如果你正在使用Java8,那么首先应该考虑的选择是使用DefaultLifecycleObserver
而不是LifecycleObserver
。
- 如果业务类同时实现
DefaultLifecycleObserver
和LifecycleEventoServer
,则将首先调用DefaultLifecycleObserver
的方法,然后再调用LifecycleEventoServer.onStateChanged(LifecycleOwner,Lifecycle.Event) - 如果一个类实现了
DefaultLifecycleObserver
,又同时使用了OnLifecycleEvent
注解,那么注解方法将被忽略。
使用Lifecycle监听Service的生命周期
在上面我们介绍了如何在组件中监听Activity/Fragment的生命周期,在Android中Service同样是一个拥有生命周期的重要组件。
为了便于对Service生命周期的监听,达到解耦Service与组件的目的,Google提供了一个LifecycleService的类。该类继承自Service,并实现了LifeCycleOwner接口,与Activity/Fragment类似,它也提供了一个名为getLifeCycle()的方法供我们使用,除此以外,它与普通的Service使用起来并无差别。LifecycleService的源码如下:
public class LifecycleService extends Service implements LifecycleOwner {
private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);
@CallSuper
@Override
public void onCreate() {
mDispatcher.onServicePreSuperOnCreate();
super.onCreate();
}
@CallSuper
@Nullable
@Override
public IBinder onBind(@NonNull Intent intent) {
mDispatcher.onServicePreSuperOnBind();
return null;
}
@SuppressWarnings("deprecation")
@CallSuper
@Override
public void onStart(@Nullable Intent intent, int startId) {
mDispatcher.onServicePreSuperOnStart();
super.onStart(intent, startId);
}
// this method is added only to annotate it with @CallSuper.
// In usual service super.onStartCommand is no-op, but in LifecycleService
// it results in mDispatcher.onServicePreSuperOnStart() call, because
// super.onStartCommand calls onStart().
@CallSuper
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@CallSuper
@Override
public void onDestroy() {
mDispatcher.onServicePreSuperOnDestroy();
super.onDestroy();
}
@Override
@NonNull
public Lifecycle getLifecycle() {
return mDispatcher.getLifecycle();
}
}
Android原生的Service因为并未实现LifecycleOwner接口,所以LiveData等需要感知生命周期组件,就无法在Service中使用。为了解决这个问题,Android中提供了一个支持Lifecycle功能的LifecycleService
。
1.在 Service 中使用 Lifecycle 首先需要在build.gradle
中添加相关依赖
dependencies {
def lifecycle_version = "2.3.1"
// optional - helpers for implementing LifecycleOwner in a Service
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"
}
2.添加相应的依赖之后,我们在创建Service时需要让它继承LifecycleService,LifecycleService是Service的子类,它在Service的基础上实现了LifecyclerOwner接口,并提供getLifecycle()方法以便我们使用。除此以外,它与普通的Service使用起来并无差别。
public class MainService extends LifecycleService {
public MyLifecycleObserver observer;
public MainService() {
observer = new MyLifecycleObserver();
getLifecycle().addObserver(observer);
}
}
使用Lifecycle监听Application的生命周期
具有生命周期的系统组件,除了Activity、Fragment和Service外,还有Application。很多时候,我们会遇到这样的需求:我们想知道应用程序当前是前台还是后台,或者当应用程序从后台回到前台时,我们能够得到通知。以前也有不少方案能实现,但是大多比较繁琐,现在利用Lifecycle组件中的ProcessLifecycleOwner,可以非常轻松的监控整个应用程序的生命周期。
1.监听 Application 的生命周期,首先需要在build.gradle
中添加相关依赖
dependencies {
def lifecycle_version = "2.3.1"
// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
}
2.然后,定义一个AppLifecycle的类,该类实现LifecycleObserver接口,负责监控整个应用程序的生命周期。
public class AppLifecycle implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onAppCreate() {
// 在应用的生命周期内,只会被回调一次
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onAppStart() {
// 当应用在前台出现时被回调
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onAppResume() {
// 当应用在前台出现时被回调
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onAppPause() {
// 当应用退出到后台时被回调
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onAppStop() {
// 当应用退出到后台时被回调
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onAppDestroy() {
// 永远不会被调用,系统不会分发ON_DESTROY事件
}
}
需要注意的是,监控应用程序生命周期的时候,Lifecycle.Event.ON_CREATE只会被回调一次,Lifecycle.Event.ON_DESTROY则永远不会被回调。
3.接下来在Application中使用ProcessLifecycleOwner.get().getLifecycle().addObserver()方法添加观察者,示例如下:
public class AbsApplication extends Application {
@Override
public void onCreate() {
ProcessLifecycleOwner.get().getLifecycle().addObserver(new AppLifecycle());
super.onCreate();
}
}
实际上监听整个应用生命周期并不需要在Application中添加观察者,我们可以在任意合适的地方调用 ProcessLifecycleOwner.get().getLifecycle().addObserver(new AppLifecycle()),但是,如果你需要监听Lifecycle.Event.ON_CREATE事件,就必须在Application生命周期进入OnCreate()之前完成观察者的添加。
Lifecycle原理解析
Fragment是如何实现Lifecycle的
Fragemnt中关于Lifecycle的核心代码如下
public class Fragment implements LifecycleOwner {
LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
void performCreate(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
void performStart(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
}
.....
void performResume(){
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
}
Fragment中主要就是实现LifecycleOwner
接口,然后通过LifecycleRegistry
来分发各个生命周期的事件。LifecycleRegistry
是整个Lifecycle组件最核心的功能。LifecycleRegistry
的工作原理非常复杂,我们在之后的章节中再做介绍。
Activity是如何实现Lifecycle的
Activity在实现上并不类似Fragment,而是额外在Activity中加入了一个ReportFragment
来实现对生命周期的分发,主要目的是为了兼容一些不继承自AppComponentActivity
的Activity也可以使用Lifecycle的特性。核心源码如下:
public class ComponentActivity extends Activity implements LifecycleOwner{
private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
@NonNull
@Override
public Lifecycle getLifecycle() {
return mLifecycleRegistry;
}
protected void onCreate(Bundle bundle) {
super.onCreate(savedInstanceState);
ReportFragment.injectIfNeededIn(this);
}
接下来我们继续分析ReportFragment
。ReportFragment
中没有加载布局,所以他在Activity中实际是是一个不可见Fragment。它的源码也很简单,本质上就是通过FragmentManager
将Fragment加载到Activity中,然后Fragment的生命周期发生变化时,获取Activity中的LifecycleRegistry
对象,将事件分发出去。
public class ReportFragment extends Fragment{
public static void injectIfNeededIn(Activity activity) {
android.app.FragmentManager manager = activity.getFragmentManager();
if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
manager.executePendingTransactions();
}
}
@Override
public void onStart() {
super.onStart();
dispatch(Lifecycle.Event.ON_START);
}
@Override
public void onResume() {
super.onResume();
dispatch(Lifecycle.Event.ON_RESUME);
}
@Override
public void onPause() {
super.onPause();
dispatch(Lifecycle.Event.ON_PAUSE);
}
@Override
public void onDestroy() {
super.onDestroy();
dispatch(Lifecycle.Event.ON_DESTROY);
}
private void dispatch(Lifecycle.Event event) {
Lifecycle lifecycle = activity.getLifecycle();
if (lifecycle instanceof LifecycleRegistry) {
((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
}
}
Lifecycle是如何分发宿主状态的
观察者与宿主生命周期的对齐
通过查看Fragment/Activity的源代码,我们发现LifecycleRegistry
才是负责分发生命周期事件的核心,在分析LifecycleRegistry
是如何进行事件分发之前,我们先来看看我们在Activity/Fragmnent中调用的addObserver()
方法干了些什么。
@Override
public void addObserver(@NonNull LifecycleObserver observer) {
...
// 初始化一个State状态值
State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
// 将宿主状态的初始值,和传递进来的`LifecycleObserver`封装成一个`ObserverWithState`对象
ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
...
// `calculateTargetState(observer)`计算得出当前宿主的状态
State targetState = calculateTargetState(observer);
mAddingObserverCounter++;
// 循环比对宿主状态与观察者的状态,如果不同步,将`ObserverWithState`的状态前进到和宿主相同的状态
while ((statefulObserver.mState.compareTo(targetState) < 0
&& mObserverMap.contains(observer))) {
pushParentState(statefulObserver.mState);
// 根据观察者当前状态,得到它的下一步状态。需要注意,状态的前进是步进的,它并不会跳过事件,而是依次前进,多次分发。
final Event event = Event.upFrom(statefulObserver.mState);
...
// 分发状态
statefulObserver.dispatchEvent(lifecycleOwner, event);
popParentState();
// mState / subling may have been changed recalculate
targetState = calculateTargetState(observer);
}
...
}
addObserver()
的逻辑大致可以分为以下流程
- 1.初始化一个State状态值
- 2.将宿主状态的初始值,和传递进来的
LifecycleObserver
封装成一个ObserverWithState
对象 - 3.将
ObserverWithState
对象存入一个Map中 - 4.
calculateTargetState(observer)
计算得出当前宿主的状态 - 5.将
ObserverWithState
的状态前进到和宿主相同的状态- 5.1 分发状态变化,内部会调用
onStateChanged()
方法
- 5.1 分发状态变化,内部会调用
void dispatchEvent(LifecycleOwner owner, Event event) {
State newState = event.getTargetState();
mState = min(mState, newState);
// 分发状态
mLifecycleObserver.onStateChanged(owner, event);
// 观察者,内部状态更新
mState = newState;
}
通过上述分析,可以看出,addObserver
方法主要就完成两个任务,1.将宿主和观察者关联起来;2.将观察者的生命周期与宿主对齐。
但是我们有两点需要注意:
-
第一:宿主的状态并不等同于宿主的生命周期,他们的关系如下图。
宿主状态与生命周期.jpg - 第二:观察者在同步宿主状态时,是依次步进的。即使宿主状态与观察者的状态存在多个间距,也不会从
INITIALIZED
直接跳到STARTED
。
反应在开发中,我们就会观察到,如果在Activity的OnStop
中注册了一个观察者,那么注册完毕后,该观察者实际上会立即收到OnCreate
、OnStart
、OnResume
、OnPause
的回调,并最终收到OnStop
的回调。
宿主分发生命周期状态
handleLifecycleEvent()
是宿主在生命周期发生变化时,主动调用的方法,由他负责完成观察者的状态变化和事件分发,接下来我们就来看一下它的实现逻辑:
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
...
moveToState(event.getTargetState());
}
...Lifecycle
// 根据Event推导出下一步的状态
public State getTargetState() {
switch (this) {
case ON_CREATE:
case ON_STOP:
return State.CREATED;
case ON_START:
case ON_PAUSE:
return State.STARTED;
case ON_RESUME:
return State.RESUMED;
case ON_DESTROY:
return State.DESTROYED;
case ON_ANY:
break;
}
throw new IllegalArgumentException(this + " has no target state");
}
...
private void moveToState(State next) {
...
// 更新宿主的状态
mState = next;
// 同步观察者的状态
sync();
...
}
private void sync() {
LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
...
// isSynced():判断宿主的状态与观察者状态是否已经同步
while (!isSynced()) {
mNewEventOccurred = false;
// 当宿主状态发生倒退时,同步观察者的状态,并分发相应的事件
if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
backwardPass(lifecycleOwner);
}
Map.Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
//当宿主状态发生前进时,同步观察者的状态,并分发相应的事件
if (!mNewEventOccurred && newest != null
&& mState.compareTo(newest.getValue().mState) > 0) {
forwardPass(lifecycleOwner);
}
}
mNewEventOccurred = false;
}
相关逻辑在代码里已经有相应的注释,这里就不再赘述。到此为止我们就分析完了LifecycleRegistry
是如何分发宿主生命周期事件了。
网友评论