Jetpack-生命周期感知型组件

生命周期感知型组件

解耦很大程度上表现为系统组件的生命周期与普通组件之间的解耦。普通组件在使用过程中通常需要依赖于系统组件的生命周期。因为普通组件无法主动获知系统组件的生命周期事件。

生命周期感知型组件可执行响应另一个组件(如ActivityFragment)的生命周期状态的变化。

原来常规的做法是在ActivityFragment的生命周期方法中实现依赖组件的操作。但这种模式会导致代码条理性很差而且会扩展错误。

生命周期感知型组件可将依赖的代码从生命周期方法 中移入到组件 本身中。

andoridx.lifecycle软件包提供了可用于构建生命周期感知型组件的类和接口-这些组件可根据ActivityFragment的当前生命周期状态自动调整期行为。

Lifecycle

Lifecycle原理:

LifecycleOwner(被观察者);LifecycleObserver(观察者)。

通过观察者模式,实现对页面生命周期的监听。

使用 Lifecycle 进行开发之前需要先在 build.gradle 中添加如下依赖代码

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
dependencies {
def lifecycle_version = "2.2.0"
def arch_version = "2.1.0"

// 包含ViewModel和LiveData
implementation "android.arch.lifecycle:extensions:$lifecycle_version"
// 仅仅包含 ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version" // For Kotlin use viewmodel-ktx
// 仅仅包含 LiveData
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version"
// 仅仅包含 Lifecycles (without ViewModel or LiveData)
implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

// Saved state module for ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:$lifecycle_version"

// Annotation processor
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycle_version" // For Kotlin use kapt instead of annotationProcessor
// alternately - if using Java8, use the following instead of lifecycle-compiler (如果用Java8, 用于替代compiler)
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"

// optional - helpers for implementing LifecycleOwner in a Service
implementation "androidx.lifecycle:lifecycle-service:$lifecycle_version"

// optional - ProcessLifecycleOwner provides a lifecycle for the whole application process
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"

// optional - ReactiveStreams support for LiveData (可选,ReactiveStreams对LiveData的支持)
implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version"

// optional - Test helpers for LiveData (可选,LiveData的测试)
testImplementation "androidx.arch.core:core-testing:$arch_version"
}

Lifecycle是一个类,用于存储有关组件(如ActivityFragment)的生命周期状态的信息,并允许其他对象观察此状态。

Lifecycle使用两种主要枚举跟踪其关联组件的生命周期状态:

事件

从框架和 Lifecycle 类分派的生命周期事件。这些事件映射到 Activity 和 Fragment 中的回调事件。

状态

Lifecycle 对象跟踪的组件的当前状态。

构成 Android Activity 生命周期的状态和事件

可将状态看做图中的节点,事件看做这些节点之间的边。

类可通过向其方法添加注解来监控组件的生命周期状态。然后,通过调用 Lifecycle 类的 addObserver()方法并传递观察者的实例来添加观察者

1
2
3
4
5
6
7
8
9
10
11
public class MyObserver implements LifecycleObserver{
@OnLifecleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener(){
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener(){
...
}
}
myLifecleOwner.getLifecycle().addObserver(new MyObserver());

例子:

没有用生命周期感知组件的代码,可能是这样

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
class MyLocationListener{
public MyLocationListener(Context context, Callback callback){
//...
}
void start(){
//connect to system location service
}
void stop(){
//disconnect from system location service
}
}

class MyActivity extends AppCompatActivity{
private MyLocationListener myLocationListener;

@Override
public void onCreate(...){
myLocationListener = new MyLocationListener(this, (location) -> {
// update UI
})
}

@Override
public void onStart(){
super.onStart();
myLocationListener.start();
// manage other components that need to respond
// to the activity lifecycle
}

@Override
public void onStop() {
super.onStop();
myLocationListener.stop();
// manage other components that need to respond
// to the activity lifecycle
}
}

使用lifecycle组件的例子:

  1. 让需要感知生命周期的组件实现LifecycleObserver接口
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
39
40
41
42
43
44
45
46
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

public class MyLocationListener implements LifecycleObserver {

private Context context;

public MyLocationListener(Context context) {
this.context = context;
}

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate() {
showLog("onCreate");
}

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy() {
showLog("onDestroy");
}

@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart() {
showLog("onStart");
}

@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop() {
showLog("onStop");
}

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume() {
showLog("onResume");
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause() {
showLog("onPause");
}

private void showLog(String msg) {
Log.e("===MyLocationListener", msg);
}
}
  1. 对应 Activity 或 Fragment 实现 LifecycleOwner,并调用 getLifecycle().addObserverLifecycle().addObserver 添加观察者
1
2
3
4
5
6
7
8
9
10
11
12
13
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LifecycleOwner;

public class MainActivity extends AppCompatActivity implements LifecycleOwner{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

getLifecycle().addObserver(new MyLocationListener(this));

}
}

自定义生命周期组件

有一个自定义类想让它成为 LifecycleOwner,可以使用 LifecycleRegistry 类,但需要将事件转发到自己的类中

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
39
40
41
42
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;

public class MyCommpont implements LifecycleOwner{
private LifecycleRegistry lifecycleRegistry;

public MyCommpont(){
lifecycleRegistry = new LifecycleRegistry(this);
}
public void onCreate(){
lifecycleRegistry.markState(Lifecycle.State.CREATED);
}
public void onStart(){
lifecycleRegistry.markState(Lifecycle.State.STARTED);
}
public void onKillApp(){
lifecycleRegistry.markState(Lifecycle.State.DESTROYED);
}

@NonNull
@Override
public Lifecycle getLifecycle(){
return lifecycleRegistry;
}
}


//调用
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

MyCommpont myCommpont = new MyCommpont();
myCommpont.onCreate();
myCommpont.onStart();
myCommpont.getLifecycle().addObserver(new LocationListener(this));
}
}

LifecycleOwner

LifecycleOwner 是单一方法接口,表示类具有 Lifecycle。它具有一种方法 (即 getLifecycle()),该方法必须由类实现。如果您尝试管理整个应用进程的生命周期,请参阅 ProcessLifecycleOwner

此接口从各个类(如 FragmentAppCompatActivity抽象化 Lifecycle 的所有权,并允许编写与这些类搭配使用的组件。任何自定义应用类均可实现 LifecycleOwner 接口

实现 LifecycleObserver 的组件可与实现 LifecycleOwner 的组件完美配合,因为所有者可以提供生命周期,而观察者可以注册以观察生命周期。

生命周期感知型组件的最佳做法

  • 使界面控制器(Activity 和 Fragment)尽可能保持精简。它们不应试图获取自己的数据,而应使用 ViewModel 执行此操作,并观察 LiveData 对象以将更改体现到视图中。
  • 设法编写数据驱动型界面,对于此类界面,界面控制器的责任是随着数据更改而更新视图,或者将用户操作通知给 ViewModel。
  • 将数据逻辑放在 ViewModel 类中。ViewModel 应充当界面控制器与应用其他部分之间的连接器。不过要注意,ViewModel不负责获取数据(例如,从网络获取)。但是,ViewModel 应调用相应的组件来获取数据,然后将结果提供给界面控制器。
  • 使用数据绑定在视图与界面控制器之间维持干净的接口。这样一来,您可以使视图更具声明性,并尽量减少需要在 Activity 和 Fragment 中编写的更新代码。如果您更愿意使用 Java 编程语言执行此操作,请使用诸如 ButterKnife 之类的库,以避免样板代码并实现更好的抽象化。
  • 如果界面 很复杂,不妨考虑创建 View 或 Activity 上下文。如果 ViewModel 存在的时间比 Activity 更长(在配置更改的情况下),Activity 将泄露并且不会获得垃圾回收期的妥善处置。
  • 使用 Kotlin 协程 管理长时间运行的任务和其他可以一部运行的操作。

LifeCycles

让组件感知Activity、Fragment组件的生命周期,Activity进一步解耦

与Activity的生命周期同步的类实现 LifecycleObserver,其中方法上分别加不同的注解标记是不同的生命周期。如@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)等等(对应了Activity的生命周期)

完整例子(一个显示在当前页面停留多少时间的例子):

MainActivity.kt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 实现功能:记录用户使用当前应用的时间
*/
class MainActivity : AppCompatActivity() {

lateinit var chronometer: MyChronometer

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
chronometer = findViewById(R.id.meter)
lifecycle.addObserver(chronometer)
}
}

activity_main.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<!--前面是分,后面是秒-->
<com.ab.lifecyclesdemo.MyChronometer
android:id="@+id/meter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

MyChronometer.java

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
package com.ab.lifecyclesdemo;

import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.widget.Chronometer;

import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;

public class MyChronometer extends Chronometer implements LifecycleObserver {

private static long elapsedTime = 0L;//记录退出的时候的时间;用静态是为了屏幕翻转的时候不重置
/**
* 要用到xml中,所以要至少有两个参数的构造方法
* @param context
* @param attrs
*/
public MyChronometer(Context context, AttributeSet attrs) {
super(context, attrs);
setBase(SystemClock.elapsedRealtime()); //系统启动后的时间 //System.currentTimeMillis() //UNIX 时间 1970 1-1
}

@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
protected void pauseMeter(){
elapsedTime = SystemClock.elapsedRealtime() - getBase();
stop();
}

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
private void resumeMeter(){
setBase(SystemClock.elapsedRealtime() - elapsedTime);
start();
}
}

新版SDK包中Activity、Fragment默认实现了LifecycleOwner接口。LifecycleOwner接口只有一个 getLifecycle(LifecycleObserver observer)方法。

如果是要监听 Service 的生命周期,则可以让 自己的Service类实现 LifecycleOwner 接口,再重写的 getLifecycle() 方法中的返回

1
2
3
4
5
6
7
8
9
public class LifecycleService extends Service implements LifecycleOwner{
//...
private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);

@Override
public Lifecycle getLifecycle(){
return mDispatcher.getLifecycle();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//使用
public class MyService extends LifecycleService{
private MyServiceObserver myServiceObserver;
public MyService(){
myServiceObserver = new MyServiceObserver();
//将观察者与被观察者绑定
getLifecycle().addObserver(myServiceObserver);
}
}

public class MyServiceObserver implements LifecycleObserver{
private String TAG = this.getClass().getName();
//当 Service 的 onCreate() 方法被调用时,该方法会被调用
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
private void startGetLocation(){
Log.d(TAG, "startGetLocation()");
}

//当 Service 的 onDestroy() 方法被调用时,该方法会被调用
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
private void stopGetLocation(){
Log.d(TAG, "stopGetLocation()");
}
}

ProcessLifecycleOwner的具体用法

1
2
3
dependencies{
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
}
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class MyApplication extends Application{
@Override
public void onCreate(){
super.onCreate();
ProcessLifecycleOwner.get().getLifecycle().addObserver(new ApplicationObserver());
}
}

public class ApplicationObserver implements LifecycleObserver{
private String TAG = this.getClass().getName();

/**
* 在应用程序的整个生命周期中只会被调用一次
*/
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate(){
Log.d(TAG, "Lifecycle.Event.ON_CREATE");
}

/**
* 当应用程序在前台出现时被调用
*/
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart(){
Log.d(TAG, "Lifecycle.Event.ON_START");
}

/**
* 当应用程序在前台出现时被调用
*/
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume(){
Log.d(TAG, "Lifecycle.Event.ON_RESUME");
}

/**
* 当应用程序退出到后台时被调用
*/
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause(){
Log.d(TAG, "Lifecycle.Event.ON_PAUSE");
}

/**
* 当应用程序退出到后台时被调用
*/
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onStop(){
Log.d(TAG, "Lifecycle.Event.ON_STOP");
}

/**
* 永远不会被调用,系统不会分发调用 ON_DESTROY 事件
*/
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
public void onDestroy(){
Log.d(TAG, "Lifecycle.Event.ON_DESTROY");
}
}