android.arch.lifecycle 包提供了能够用于构建生命周期感知(lifecycle-aware)组件的类和接口,这些组件能够根据 Activity 或 Fragment 的当前生命周期自动调整其行为。javascript
注:导入 android.arch.lifecycle 到项目中请参看添加组件到项目html
Android Framework 中定义的大多数应用程序组件都附有生命周期。这些生命周期由操做系统或在进程中运行的框架代码管理。它们是 Android 运行的核心而且应用程序必须遵照它们,不这样作可能会致使内存泄漏甚至应用程序崩溃。java
假设咱们有一个须要在屏幕上显示设备位置的 Activity。常见的实现方式可能以下所示:android
class MyLocationListener {
public MyLocationListener(Context context, Callback callback) {
// ...
}
void start() {
// 连接到系统定位服务
}
void stop() {
// 断开系统定位服务
}
}
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, (location) -> {
// 更新 UI
});
}
public void onStart() {
super.onStart();
myLocationListener.start();
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}复制代码
尽管这个例子看起来不错,在真正的应用程序中,你最终会有太多的相似调用而且会致使 onStart() 和 onStop() 方法变的很是臃肿。git
另外,一些组件不能在 onStart() 方法中当即启动。若是咱们须要在启动位置观察者以前检查一些配置怎么办?在某些状况下极可能发生 Activity 中止后才检查配置完成,这意味着在 myLocationListener.stop() 被调用以后 myLocationListener.start() 才被调用,会致使定位服务基本上永远保持链接。github
class MyActivity extends AppCompatActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, location -> {
// 更新 UI
});
}
public void onStart() {
super.onStart();
Util.checkUserStatus(result -> {
// 若是这个回调在 Activity 中止后被调用怎么办?
if (result) {
myLocationListener.start();
}
});
}
public void onStop() {
super.onStop();
myLocationListener.stop();
}
}复制代码
android.arch.lifecycle 包提供了类和接口帮助以弹性和隔离的方式解决这些问题。网络
Lifecycle 是一个类,它持有关于组件(如 Activity 或 Fragment)生命周期状态的信息,而且容许其余对象观察此状态。app
Lifecycle 使用两个主要的枚举来跟踪其关联组件的生命周期状态。框架
Eventide
生命周期事件是从框架和 Lifecycle 发出的事件。这些事件映射到 Activity 和 Fragment 中的回调事件。
State
Lifecycle 对象跟踪的组件的当前状态。
将状态视为图表的节点,事件做为这些节点之间的边缘。
类能够经过向其方法添加注释来监控组件的生命周期状态。
public class MyObserver implements LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
public void onResume() {
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
public void onPause() {
}
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());复制代码
LifecycleOwner 是一个单一方法的接口,它表示实现类具备一个 Lifecycle。它有一个 getLifecycle()) 方法,该方法必须由实现类实现。
该实现类从个别的类(例如 Activity 和 Fragment)提取生命周期的全部权,而且容许编写可与二者兼容的组件。任何自定义应用程序类均可以实现 LifecycleOwner 接口。
注:因为 Architecture Components 处于 alpha 阶段,因此 Fragment 和 AppCompatActivity 不能实现 LifecycleOwner (由于咱们不能在稳定的组件中添加依赖不稳定的API)。在 Lifecycle 稳定以前,为了方便提供了 LifecycleActivity 和 LifecycleFragment 类。在 Lifecycles 项目发布后,支持库中的 Fragment 和 Activity 将会实现 LifecycleOwner 接口;届时 LifecycleActivity 和 LifecycleFragment 将会被弃用。另请参阅在自定义 Activity 和 Fragment 中实现 LifecycleOwner。
对于上面的例子,咱们可使 MyLocationListener 类成为 LifecycleObserver 而后在 onCreate 中使用 Lifecycle 初始化它。这样让 MyLocationListener 类自给自足,意味着在必要的时候它能对本身进行清理。
class MyActivity extends LifecycleActivity {
private MyLocationListener myLocationListener;
public void onCreate(...) {
myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
// 更新 UI
});
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.enable();
}
});
}
}复制代码
一个常见的用例是避免在 Lifecycle 处于不良状态时调用某些回调。例如,若是在保存 Activity 状态后回调运行 Fragment 事务,将会致使崩溃,所以咱们永远不会想要调用该回调。
为了简化该用例, Lifecycle 类容许其余对象查询当前状态。
class MyLocationListener implements LifecycleObserver {
private boolean enabled = false;
public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
...
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void start() {
if (enabled) {
// 链接
}
}
public void enable() {
enabled = true;
if (lifecycle.getState().isAtLeast(STARTED)) {
// 若是没有链接则进行链接
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void stop() {
// 若是已经链接则断开链接
}
}复制代码
经过这种实现,LocationListener 类是彻底的生命周期感知(lifecycle-aware);它能够进行本身的初始化或清理操做,而不受其 Activity 的管理。若是须要在其它的 Activity 或其余的 Fragment 中使用 LocationListener,只须要初始化它。全部的安装和卸载操做都由类本身管理。
能够与 Lifecycle 一块儿使用的类称为生命周期感知(lifecycle-aware) 组件。鼓励有须要使用 Android 生命周期的类的库提供生命周期感知(lifecycle-aware) 组件,以便于用户能够轻松的在客户端集成这些类,而不须要手动管理生命周期。
LiveData 是一个生命周期感知(lifecycle-aware) 组件的示例。与 ViewModel 一块儿使用 LiveData 能够在遵照 Android 生命周期的前提下,更容易地使用数据填充UI。
保持 UI 控制器(Activity 和 Fragment)尽量的精简。它们不该该试图去获取它们所需的数据;相反,要用 ViewModel 来获取,而且观察 LiveData 将数据变化反映到视图中。
尝试编写数据驱动(data-driven)的 UI,即 UI 控制器的责任是在数据改变时更新视图或者将用户的操做通知给 ViewModel。
将数据逻辑放到 ViewModel 类中。ViewModel 应该做为 UI 控制器和应用程序其它部分的链接服务。注意:不是由 ViewModel 负责获取数据(例如:从网络获取)。相反,ViewModel 调用相应的组件获取数据,而后将数据获取结果提供给 UI 控制器。
使用 Data Binding 来保持视图和 UI 控制器之间的接口干净。这样可让视图更具声明性,而且尽量减小在 Activity 和 Fragment 中编写更新代码。若是你喜欢在 Java 中执行该操做,请使用像 Butter Knife 这样的库来避免使用样板代码并进行更好的抽象化。
若是 UI 很复杂,能够考虑建立一个 Presenter 类来处理 UI 的修改。虽然一般这样作不是必要的,但可能会让 UI 更容易测试。
不要在 ViewModel 中引用 View 或者 Activity 的 context。由于若是 ViewModel 存活的比 Activity 时间长(在配置更改的状况下),Activity 将会被泄漏而且没法被正确的回收。
任何自定义的 Fragment 或 Activity 均可以经过实现内置的 LifecycleRegistryOwner 接口转换为 LifecycleOwner(而不是继承 LifecycleActivity 或 LifecycleFragment)
public class MyFragment extends Fragment implements LifecycleRegistryOwner {
LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);
@Override
public LifecycleRegistry getLifecycle() {
return lifecycleRegistry;
}
}复制代码
若是要建立一个 LifecycleOwner 的自定义类,可使用 LifecycleRegistry 类,可是须要将事件转发到该自定义类中。若是是 Fragment 和 Activity 实现了 LifecycleRegistryOwner 接口,则此转发会自动完成。