Android官方Architecture架构组件使用介绍之lifecycle

Android Architecture Components
官方是这么介绍它的:可以帮助您设计健壮的、可测试的、可维护的应用程序。用于管理UI组件的生命周期和处理数据持久性。
这是在https://developer.android.google.cn上Google强烈推荐的一个库。
它真值得在项目中使用么,有何优势呢?带着这些疑问,我们来了解这强大的组件吧。
该组件包括:

  • lifecycle 处理生命周期,创建一个自动响应生命周期事件的用户界面
  • LiveData 构建底层数据库更改时通知试图的数据对象(数据驱动界面)
  • ViewModel 存储未在应用旋转中销毁的UI相关数据
  • Room 使用应用内对象和编译时检查来访问您的应用的SQLite数据库
  • Paging 逐步从数据源加载所需的信息

今天主要了解一下lifecycle,对于那些需要在Activity或Fragment各生命周期处理不同业务的人来说,这个库真的值得一试。


lifecycle简介

lifecycle支持生命周期的组件执行操作以响应另一个组件(例如Activity和Fragment)的生命周期状态更改。它可帮助您生成组织性更好,并且通常重量更轻的代码,这些代码更易于维护。

实例解剖

比如我们有一个在屏幕上显示设备位置的Activity:

  • 需要在 onStart()中需要调用LocationListener.onStart()
  • 需要在 onStop()中需要调用LocationListener.onStop()
    (在项目中,直接这种方式调用,也本没有啥问题。)

但,实际应用程序中,您最终会有太多的调用来管理UI和其他组件以响应当前的生命周期状态。
管理多个组件会在生命周期方法中放置大量代码,例如onStart()和 onStop(),这使得它们很难维护。

而且,不保证组件在Activity或Fragment停止之前启动。如果我们需要执行长时间运行的操作。这可能会导致竞争条件在onStop()方法完成之前完成onStart(),使组件保持比所需时间更长的时间。
(简单说就是,如果当前Activity已经被销毁了,这个时候执行了回调可能引发异常)

对于这种情况,lifecycle就可以有更好的处理方案,自动跟随当前的组件生命周期。
并且一个lifecycle可以实现绑定多个组件,无多余代码侵入,逻辑思维更清晰

生命周期

Lifecycle 是一个持有组件生命周期状态(如Activity或Fragment)的信息的类,并允许其他对象观察此状态

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

  • Event
  • State

Lifecycle对象跟踪的组件的当前状态,如图:

简单示例

导入依赖

对于当前的lifecycle,其实您只需要将您项目的支持库升级到26.1.0或更高即可

其他库相关库导入示例,可暂不需了解

  • 根项目中,添加google远程 repositories
    1
    2
    3
    4
    5
    allprojects {
    repositories {
    google()
    }
    }
  • 当前app model中添加依赖库
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    dependencies {
    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:1.1.1"
    // alternatively, just ViewModel
    implementation "android.arch.lifecycle:viewmodel:1.1.1"
    // alternatively, just LiveData
    implementation "android.arch.lifecycle:livedata:1.1.1"

    annotationProcessor "android.arch.lifecycle:compiler:1.1.1"

    // Room (use 1.1.0-beta3 for latest beta)
    implementation "android.arch.persistence.room:runtime:1.0.0"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

    // Paging
    implementation "android.arch.paging:runtime:1.0.0-rc1"

    // Test helpers for LiveData
    testImplementation "android.arch.core:core-testing:1.1.1"

    // Test helpers for Room
    testImplementation "android.arch.persistence.room:testing:1.0.0"
    }
    Java 8 Support for Lifecycles

示例介绍

一个类可以通过向其方法添加注释来监视组件的生命周期状态。然后,您可以通过调用 该类的 addObserver() 方法Lifecycle并传递观察者的实例来添加观察者,如下例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyObserver implements LifecycleObserver {

//当组件执行onResume的时候就会执行connectListener()方法
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void connectListener() {
...
}

//当组件执行onPause的时候就会执行connectListener()方法
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void disconnectListener() {
...
}
}

myLifecycleOwner.getLifecycle().addObserver(new MyObserver());

在上面的例子中,该myLifecycleOwner对象实现了 LifecycleOwner 接口,下面为您讲解该类

LifecycleOwner

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

该接口需要提供拥有生命周期的组件,故需要在Fragment或AppCompatActivity等组件的子类中进行实现

对于上述定位相关的示例,我们便可以如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class MyActivity extends AppCompatActivity {

private MyLocationListener myLocationListener;

public void onCreate(...) {

//在onCreate方法,提供LifecycleRegistry给LifecycleObserver提供一个拥有生命周期的组件

myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// update UI
});

Util.checkUserStatus(result -> {
if (result) {
//在我们需要进行定位操作的时候,执行定位开启逻辑
myLocationListener.enable();
}
});
}

}
  • LifecycleObserver 实现不依赖 AppCompatActivity 侵入代码,实现各生命周期对应的逻辑
    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
    class MyLocationListener implements LifecycleObserver {
    private boolean enabled = false;
    private Lifecycle lifecycle;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
    this.lifecycle = lifecycle;
    ...
    }

    //在 AppCompatActivity 的onStart 逻辑中调用 定位connect逻辑
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
    if (enabled) {//在该逻辑开启的情况下执行
    // connect
    }
    }

    public void enable() {
    enabled = true;//开启该逻辑
    if (lifecycle.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {//表示当前组件生命周期执行在State.STARTED期间
    // connect if not connected
    }
    }


    //在 AppCompatActivity 的onStart 逻辑中调用 定位disconnect if connected逻辑
    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
    // disconnect if connected
    }
    }

通过这个实现,我们的LocationListener类完全是有生命周期感知的。如果我们需要使用LocationListener在其他Activity或Fragment,我们只需要初始化它。所有的设置和拆卸操作都由该类本身进行管理。

自定义LifecycleOwner

支持库中的Fragment和Activity 26.1.0和更高版本已经实现了该LifecycleOwner 接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class MyActivity extends Activity implements LifecycleOwner {
private LifecycleRegistry mLifecycleRegistry;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mLifecycleRegistry = new LifecycleRegistry(this);
mLifecycleRegistry.markState(Lifecycle.State.CREATED);//手动触发状态State.CREATED
getLifecycle().addObserver(new MyLifecycleObserver());
}

@Override
public void onStart() {
super.onStart();
mLifecycleRegistry.markState(Lifecycle.State.STARTED);//手动触发状态State.STARTED
}

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

使用

1
2
3
4
5
6
7
8
class MyLifecycleObserver implements LifecycleObserver {

@OnLifecycleEvent(Lifecycle.State.CREATED)
public void onCreate(){}//组件markState Lifecycle.State.CREATED 时执行

@OnLifecycleEvent(Lifecycle.State.STARTED)
public void onStart(){}//组件markState Lifecycle.State.STARTED 时执行
}

生命周期感知组件的最佳实践

  • 尽可能保持您的UI控制器(Activity和Fragment)尽可能精简。(他们不应该试图获取他们自己的数据; 相反,使用ViewModel来做到这一点,并观察一个LiveData 对象,以反映到视图的变化。)
  • 尝试编写数据驱动的用户界面,其中您的用户界面控制器的职责是在数据更改时更新视图,或将用户操作通知给用户 ViewModel。
  • 把你的数据逻辑放在你的 ViewModel上。 ViewModel应该充当您的UI控制器和其他应用程序之间的连接器。但要小心,ViewModel取数据不是及时的(例如,从网络)。相反, ViewModel应该调用适当的组件来获取数据,然后将结果提供给UI控制器。
  • 使用数据绑定在视图和UI控制器之间保持干净的界面。这使您可以使您的视图更具说明性,并最大限度地减少需要在Activity和Fragment中编写的更新代码。如果你喜欢用Java编程语言来做到这一点,可以使用像Butter Knife这样的库 来避免样板代码并获得更好的抽象。
  • 如果您的UI很复杂,请考虑创建一个 presenter 类来处理UI修改。这可能是一项艰巨的任务,但它可以使您的UI组件更易于测试。
  • 避免在你的应用中引用一个View或Activity 的上下文 给ViewModel。如果ViewModel超出了Activity的生命周期(在配置发生变化的情况下),则Activity会泄漏并且垃圾收集器无法妥善处理。
  • 最好结合onSaveInstanceState()方法,处理好被系统回收导致未执行onStop的情况

推荐阅读