Google官方架构组件Lifecycle和LiveData

前言

在Google 2017年的IO大会上面发布了一些可以帮助开发人员创建更容易维护和更强大的应用程序,Lifecycle就是其中的一个,它可以帮助我们更好的处理Android组件和声明周期相关的问题。

Lifecycle

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

引入Lifecycle扩展库

1
2
implements "android.arch.lifecycle:runtime:${architectureComponentsVersion}"
implements "android.arch.lifecycle:extensions:${architectureComponentsVersion}"

继承LifecycleObserver来实现声明周期观察者接口。

1
2
3
4
5
6
7
8
9
10
11
12
public interface IPresenter extends LifecycleObserver {

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate(@NotNull LifecycleOwner owner);

@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy(@NotNull LifecycleOwner owner);

@OnLifecycleEvent(Lifecycle.Event.ON_ANY)
void onLifecycleChanged(@NotNull LifecycleOwner owner,
@NotNull Lifecycle.Event event);
}

重写对应的onCreateonDestroy方法实现具体的声明周期内逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class BasePresenter implements IPresenter {

private static final String TAG = "com.qingmei2.module.base.BasePresenter";

@Override
public void onLifecycleChanged(@NotNull LifecycleOwner owner, @NotNull Lifecycle.Event event) {

}

@Override
public void onCreate(@NotNull LifecycleOwner owner) {
Log.d("tag", "BasePresenter.onCreate" + this.getClass().toString());
}

@Override
public void onDestroy(@NotNull LifecycleOwner owner) {
Log.d("tag", "BasePresenter.onDestroy" + this.getClass().toString());
}
}

在Activity/Fragment容器中添加Observer,注册具体的观者对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class MainActivity extends AppCompatActivity {
private IPresenter mPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("tag", "onCreate" + this.getClass().toString());
setContentView(R.layout.activity_main);
mPresenter = new MainPresenter(this);
//添加LifecycleObserver
getLifecycle().addObserver(mPresenter);
}

@Override
protected void onDestroy() {
Log.d("tag", "onDestroy" + this.getClass().toString());
super.onDestroy();
}
}

如此,每当Activity发生了对应的生命周期改变,Presenter就会执行对应事件注解的方法。除onCreate和onDestroy事件之外,Lifecycle一共提供了所有的生命周期事件,只要通过注解进行声明,就能够使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
 public enum Event {
/**
* Constant for onCreate event of the {@link LifecycleOwner}.
*/
ON_CREATE,
/**
* Constant for onStart event of the {@link LifecycleOwner}.
*/
ON_START,
/**
* Constant for onResume event of the {@link LifecycleOwner}.
*/
ON_RESUME,
/**
* Constant for onPause event of the {@link LifecycleOwner}.
*/
ON_PAUSE,
/**
* Constant for onStop event of the {@link LifecycleOwner}.
*/
ON_STOP,
/**
* Constant for onDestroy event of the {@link LifecycleOwner}.
*/
ON_DESTROY,
/**
* An {@link Event Event} constant that can be used to match all events.
*/
ON_ANY
}

例如这样:

1
2
3
4
5
6
7
8
9
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void unregisterObserver() {
lifecycle.removeObserver(this);
}

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void sendDummyLocation() {
locationListener.updateLocation(LOCATION);
}

以Fragment为例,Activity是类似的,类的结构关系如下:

Lifecycle类的结构关系

LifecycleObserver接口( Lifecycle观察者):实现该接口的类,通过注解的方式,可以通过被LifecycleOwner类的addObserver(LifecycleObserver o)方法注册,被注册后,LifecycleObserver便可以观察到LifecycleOwner的生命周期事件。

LifecycleOwner接口(Lifecycle持有者):实现该接口的类持有生命周期(Lifecycle对象),该接口的生命周期(Lifecycle对象)的改变会被其注册的观察者LifecycleObserver观察到并触发其对应的事件。

Lifecycle(生命周期):和LifecycleOwner不同的是,LifecycleOwner本身持有Lifecycle对象,LifecycleOwner通过其Lifecycle getLifecycle()的接口获取内部Lifecycle对象。

State(当前生命周期所处状态):如图所示。

Event(当前生命周期改变对应的事件):如图所示,当Lifecycle发生改变,如进入onCreate,会自动发出ON_CREATE事件。

Fragment(Activity同理)实现了LifecycleOwner接口,这意味着Fragment对象持有生命周期对象(Lifecycle),并可以通过Lifecycle getLifecycle()方法获取内部的Lifecycle对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Fragment implements xxx, LifecycleOwner {

//...省略其他

LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

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

public interface LifecycleOwner {
@NonNull
Lifecycle getLifecycle();
}

LifecycleRegistry 本身就是一个成熟的 Lifecycle 实现类,它被实例化在Activity和Fragment中使用,如果我们需要自定义LifecycleOwner 并实现接口需要返回一个Lifecycle实例,完全可以直接在自定义LifecycleOwner中new一个LifecycleRegistry成员并返回它(简而言之就是:直接拿来用即可)。其次,Google的Lifecycle库中提供了一个 DefaultLifecycleObserver 类,方便我们直接实现LifecycleObserver接口,相比较于文中demo所使用的注解方式,Google官方更推荐我们使用 DefaultLifecycleObserver 类。

LiveData

对于用过RxJava的朋友可能会对这个LiveData感到熟悉,它们所做的事情大致一样。LiveData可以由感兴趣的一放订阅,在每次数据发生变化的时候通知订阅方,和RxJava不同的是它可以感知并遵循Activity、Fragment或Service等组件的生命周期。正是由于LiveData对组件生命周期可感知特点,因此可以做到仅在组件处于生命周期的激活状态时才更新UI数据。

LiveData需要一个观察者对象,一般是Observer类的具体实现。当观察者的生命周期处于STARTED或RESUMED状态时,LiveData会通知观察者数据变化;在观察者处于其他状态时,即使LiveData的数据变化了,也不会通知。

LiveData可以使用如下方法注册观察者:

1
2
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {}

第一个参数为LifecycleOwner,在新的兼容库中,Activity、Fragment等都实现了LifecycleOwner接口。LifecycleOwner可以获取Lifecycle,从而得到组件的各生命周期状态。

第二个参数为观察者对象,当数据源变化时就会回调。

通过LiveData的observe方法进行关系绑定,就可以在组件的生命周期状态变为DESTROYED时移除观察者,这样Activity或Fragment就可以安全地观察LiveData而不用担心造成内存泄露。

使用场景

在ViewModel中创建LiveData,并持有某种类型的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class NameViewModel extends ViewModel {

// Create a LiveData with a String
private MutableLiveData<String> mCurrentName;

public MutableLiveData<String> getCurrentName() {
if (mCurrentName == null) {
mCurrentName = new MutableLiveData<String>();
}
return mCurrentName;
}

// Rest of the ViewModel...
}

创建一个Observer对象并实现其onChanged()回调,一般在Activity或Fragment中创建Observer。

在Activity或Fragment中通过LiveData的observe(@NonNull LifecycleOwner owner, @NonNull Observerobserver)方法建立观察关系。

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
public class NameActivity extends AppCompatActivity {

private NameViewModel mModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

// Other code to setup the activity...

// Get the ViewModel.
mModel = ViewModelProviders.of(this).get(NameViewModel.class);

// Create the observer which updates the UI.
final Observer<String> nameObserver = new Observer<String>() {
@Override
public void onChanged(@Nullable final String newName) {
// Update the UI, in this case, a TextView.
mNameTextView.setText(newName);
}
};

// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.
mModel.getCurrentName().observe(this, nameObserver);
}
}

LiveData没有对外提供公有的修改数据的方法,而其子类MutableLiveData提供了setValue(T)(主线程使用)和postValue(T)(子线程使用)两个方法允许修改数据。MutableLiveData源码定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
*
* @param <T> The type of data hold by this instance
*/
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}

@Override
public void setValue(T value) {
super.setValue(value);
}
}

在前几步的基础上,我们通过一个按钮来触发修改LiveData数据,看对应的UI是否得到更新:

1
2
3
4
5
6
7
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String anotherName = "John Doe";
mModel.getCurrentName().setValue(anotherName);
}
});

当触发LiveData的setValue(T)时,观察者对象的onChanged()被回调,从而更新UI。

LiveData结合Room使用

Room 是Android官方的持久化数据库方案,支持返回LiveData对象,当数据库变化时会更新LiveData,这些逻辑由Room自动生成。

上述逻辑是在后台异步进行的,这种模式可以使UI跟数据库的数据保持同步。

更多关于Room的用法可参考 Room persistent library guide