Android LifeCycle详解

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;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myLocationListener=new MyLocationListener(this, new MyLocationListener.OnLocationChangeListener() {
    
    
            @Override
            public 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  {
    
    
    @Override
    public 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 。

猜你喜欢

转载自blog.csdn.net/xuefu_78/article/details/112310226