[简译]Google 官方 App 架构 Guide(3)
Contents
本文将介绍Architecture Components中的Lifecycle组件
Handling Lifecycles
android.arch.lifecycle
包提供了能够构建拥有 lifecycle-aware 能力的组件的类和接口。 lifecycle-aware 在这里是指能自动感知activity或者fragment生命周期,并随之自动调整自己行为的能力。
Android应用的大部分组件都是要么是系统自带生命周期的,要么框架管理的。如果无视这些,很有可能带来的后果是crash或者内存泄露。
举个例子:在activity中显示设备地址,通常的做法会将MyLocationListener
和MyActivity
的生命周期绑定在一起。
class MyLocationListener { |
尽管上面的代码看起来没问题,但是——onStart()
以及 onStop()
中慢慢会积累越来越多的这种注册、反注册调用。
有时,也有可能components是在某个回调中starting,比如location observer start()在Activity onStop
之后被调用,这意味着myLocationListener.start()
会在stop
之后重启。
class MyActivity extends AppCompatActivity { |
下面就要开始推销android.arch.lifecycle
了
Lifecycle
Lifecycle
是一个状态类,主要维护了两个枚举值,来跟踪 component 的lifecycle
- Event
由
Lifecycle
和Framework派发,这些event注册到对应的activities 和fragments的回调事件
- State
记录component 当前的生命周期状态
用图数据结构理解的话,status就是节点,而event是连接各个节点的边。
要想监控component的生命周期,只需要在对应方法上面添加相应annotations
public class MyObserver implements LifecycleObserver { |
LifecycleOwner
LifecycleOwner
只是一个单一方法接口类,用于表明这个类有个Lifecycle
状态类。LifecycleOwner
通过getLifecycle()
方法将activities 或 fragments抽出来。任何类都可以实现LifecycleOwner
,没有限制。
Note: 在 alpha 阶段, Fragment
和 AppCompatActivity
还没有实现这个接口。目前可以用LifecycleActivity
和 LifecycleFragment
替代。 release后,support库中的 fragments and activities 默认会实现 LifecycleOwner
下面修改例子中的MyLocationListener
继承自LifecycleObserver
+ class MyActivity extends LifecycleActivity { |
注意上面的
if(lifecycle.getState().isAtLeast(STARTED)) |
我们有能力在回调特定方法时,随时检查lifecycle当前的状态。
比如 Fragment 有一个著名crash:在Activity state save后调用fragment transaction,就可以通过这种方式避免。good :)
LocationListener
现在已经能能感知到Activity的生命周期变化了。既不需要我们注册,也不需要注销,all is done。
像LocationListener
这种能和Lifecycle
一起工作的类被称为 lifecycle-aware components
LiveData
就是一种 lifecycle-aware component。 结合 LiveData
和 ViewModel
可以在Android Lifecycle的基础上实现UI界面数据的更新。
Lifecycle的最佳实践
- 不要在 UI controllers 中直接获取数据 (activities and fragments),使用
ViewModel
获取数据, 再通过LiveData
把数据映射到UI上。 - 推荐写数据驱动的UI,而 UI controller的职责是在数据改变时更新UI, 或者将用户交互通知到
ViewModel
- 将数据逻辑限制在
ViewModel
类中。但是获取数据(比如从网上)不是ViewModel
该做的事。ViewModel
应该是 UI controller 和其他模块的连接器。比如ViewModel
调用其他的模块去获取数据然后把结果传给UI controller。 - 通过 Data Binding 来保证 view 和 UI controller 之间接口的干净。最终目的是让 view 的变动引起的 activities 代码改动最小化。
- 如果UI足够复杂,可以考虑抽出一个Presenter来处理UI更新。虽然有点大材小用,但是可以让view更容易测试.
- 永远不要在ViewModel中直接引用
View
或者Activity
context。记住 ViewModel在Activity重建(configuration changes)后会恢复为同一个实例,那么之前引用的context就会内存泄露。
附录
在自定义 activities 或 fragments中实现LifecycleOwner
其实不用继承LifecycleFragment
或者 LifecycleActivity
,只要自定义 fragment 或者 activity 实现了LifecycleRegistryOwner
接口,它就可以被看为LifecycleOwner
,
public class MyFragment extends Fragment implements LifecycleRegistryOwner { |
如果你想让一个自定义类成为 LifecycleOwner
, 你可以用LifecycleRegistry, 只不过你得自己负责派发生命周期事件到自定义类。而对于实现了LifecycleRegistryOwner
的fragments 和 activities ,这个派发动作是自动完成的。
Author: deskid
Link: https://deskid.github.io/2017/06/01/Guide-to-App-Architecture-3/
License: 知识共享署名-非商业性使用 4.0 国际许可协议