在今年的Google I/O大会上,Google 发布了一个新的概念:Android Achitecture Component,即基于安卓的一系列更加便捷开发的基础库,主要包括便捷的生命周期管理和便捷的数据存储.这篇文章我们来看看使用其中的生命周期管理模块,如何使得EasyPusher更加便于开发和集成.
我们先认识一下开发一款类似EasyPusher这种基于摄像头的APP存在的痛点.
我们需要关注如下几个事件的变动,并适当地响应这些变动:
graph LR
ActivityCreate-->ActivityResume
ActivityResume-->TextureAvailable
ActivityResume-->onRequestPermissionsResult
onRequestPermissionsResult-->ActivityPaused
TextureAvailable-->ActivityPaused
ActivityPaused-->TextureDestoryed
TextureDestoryed-->ActivityDestoryed
- ActivityCreate VIEW初始化,回调设置,权限申请
- ActivityResume Activity到前台,尝试启动预览
- TextureAvailable Texture准备完毕,尝试启动预览
- onRequestPermissionsResult 权限获取完成,尝试启动预览
- ActivityPaused Activity到后台,关闭预览,如果未finish,尝试启动后台预览
- TextureDestoryed
- ActivityDestoryed 如果使能后台预览,尝试启动后台预览,否则关闭摄像头.
事件 | 响应 | 可能性 |
---|---|---|
ActivityCreate | VIEW初始化,回调设置,权限申请 | Activity 可能初次启动,也有可能在后台恢复;摄像头有可能已经在后台运行,也有可能尚未启动 |
ActivityResume | Activity到前台,(根据摄像头的权限申请情况)尝试启动预览 | 权限可能已经申请过了,也可能没有; |
TextureAvailable | Texture准备完毕,(根据摄像头的权限申请情况)尝试启动预览 | 权限可能已经申请过了,也可能没有; |
onRequestPermissionsResult | 权限获取完成,尝试启动预览 | |
ActivityPaused | Activity到后台,关闭预览,如果未finish,尝试启动后台预览 | 可能需要启动后台预览 |
ActivityDestoryed | 如果使能后台预览,尝试启动后台预览,否则关闭摄像头. | 可能需要启动后台预览 |
从图表可以看出,安卓的生命周期比较复杂不受控制.
这些存在生命周期的组件,导致依附于其的业务逻辑,需要根据组件不同的生命阶段做出不同的逻辑处理.典型的就是在onCreate里创建,onDestory里销毁;试想一下,一个功能复杂的APP,每一个业务逻辑模块都这样来一遍,就会导致onCreate\onDestory越来越臃肿,Activity的代码量越来越大,越来越难以维护.
再加上Activity的各种不可预测的销毁和重建,会使得这些功能更加难以维护:
App components, like activities and fragments, have a lifecycle managed by the Android Framework. The Framework may decide to destroy or re-create them based on some user actions or device events that are completely out of your control.
我们很期望这样一种机制,各个业务模块都在自己内部响应生命周期更改,这样的话Activity或者Fragment或者Service就只需要实现一种”组装”的功能,那就太好了!而我们使用Architecture Component就可以实现这样的业务模块.
Architecture Component主要有如下概念:
- ViewModel 提供一种创建和存储绑定于特定的生命周期组件的对象的方法,这里的”绑定”,指的是在特定的生命周期内有效.由组件内部进行管理,并且可以方便地进行数据共享.存储的数据目标并不会在“recreate”的时候被销毁重建,而是在系统内部进行保持。
- Lifecycle
Lifecycle 记录着一个组件 (比如activity或者fragment) 的状态,并且允许其他对象来获取这种状态.Lifecycle 使用两种枚举类型来追踪组件的生命周期.
- Event
生命周期的更改事件.由系统或者Lifecycle类来进行调度.这些事件对应着Activity或者Fragment中的一系列函数回调. - State
当前组件的生命周期的状态.
- Event
- LifecycleOwner/LifecycleRegistryOwner - 表示一种具有生命周期的组件本身,比如Activity\Fragment.
- LifecycleObserver
表示组件观察者.组件观察者通过annotation来监听组件的生命周期更改.
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());
- LiveData - 兼容了Lifecycle的可观察者。允许用户进行跨组件地观察数据更改,并且在组件终止时取消订阅。下面表示一个Location对应的LiveData类,该类实现了LiveData的onActive以及onInactive方法,并做出对应的初始化与反初始化。当位置信息更改时,调用setValue方法进行赋值,这样LiveData内部会通知各个观察者数据更新。
public class LocationLiveData extends LiveData<Location> {
private LocationManager locationManager;
private SimpleLocationListener listener = new SimpleLocationListener() {
@Override
public void onLocationChanged(Location location) {
setValue(location);
}
};
public LocationLiveData(Context context) {
locationManager = (LocationManager) context.getSystemService(
Context.LOCATION_SERVICE);
}
@Override
protected void onActive() {
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
}
@Override
protected void onInactive() {
locationManager.removeUpdates(listener);
}
}
LiveData的调用示例:
public class MyFragment extends LifecycleFragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LiveData<Location> myLocationListener = ...;
Util.checkUserStatus(result -> {
if (result) {
myLocationListener.observe(this, location -> {
// update UI
});
}
});
}
}
实际上ViewModel与LiveData的结合使用十分适用于异步加载的应用场景:
public class MyViewModel extends ViewModel {
private MutableLiveData<List<User>> users;
public LiveData<List<User>> getUsers() {
if (users == null) {
users = new MutableLiveData<List<Users>>();
loadUsers();
}
return users;
}
private void loadUsers() {
// do async operation to fetch users
}
}
再做个总结:
1. 具有生命周期(Lifecycle)的Activity,Fragment可作为一种LifecycleOwner;
2. LifecyclerObserver可获取,监测LifecycleOwner的生命周期的状态以及状态变更;
3. ViewModel可在Activty recreate的时候保持数据不被销毁,但是finish的时候销毁;同时可用于在Fragment之间方便地数据共享.
4. LiveData类似于观察者模式里的被观察者,只不过观察者只能是LifecycleOwner,同时,在观察者的生命周期终结时,自动反注册.
这几个概念,如果不应用到实践中,乍一看会觉得云里雾里,读者会觉得作者废话半天到底在逼逼叨什么?
好吧,下一篇文章我们将会看到这几个概念的组合所产生的影响和威力,届时,作者将把EasyPusher APP剥离,底层代码形成库,大家可以发现原来几行代码就可以实现一个Pusher了.