前言
为了帮助开发着打造一款优秀的 App,Google 可谓费尽心力, 推出了各种诸如 MVP,MVVM 等等项目架构的思路, 帮助开发者更加高效的开发, 尽管这样, Google 还是接着推出了一个新的项目架构, 以便给予开发者更多的选择, 至于这种架构思路和 MVP 等框架的优劣, 各位看完文章或许自有定论.
1. 生命周期
在移动操作系统上开发软件其实是十分复杂的一件事情, 因为我们随时需要面对系统和用户的各种不可预料的操作, 很多时候, 事情并不向着我们预设的方向方向进展. 因此系统向我们提供了核心组件的生命周期这种东西, 告知我们的 App 正处在什么样的状况中, 以便于我们做出相应的处理.
如上图. 虽然 Google 给出了 Activity 非常详尽的生命周期结构, 因此我们对根据生命周期做出相应的合理的安排, 比如添加和移除实时 GPS 位置监听:
可是随着业务的逐渐复杂, 我们可能在添加监听之间需要向服务器验证某些用户信息, 等返回信息正确才去监听定位. 那么在网络异步回调的时候, 我们就很难知道当前的 activity 的生命周期状态.
如果发生上图的情况, 那么我们的占用的相关资源就可能永远无法移除了. 这还只是冰山一角, 大家尽可以想想, 当我们的异步调用面对无法预知的用户操作和系统处理的时候, 什么问题都可能发生.
总而言之, 由于我们对于 UI 实时的状态做不到了如指掌, 以至于对数据和逻辑的处理就无法尽善尽美. 这是类似隐患得不到很好的解决根本原因.
2. Google 大礼包
这次 Google 推出了一套新的项目架构组件和架构思路, 从 UI 到 Data, 帮助我们更加精准的开发自己的 App.
2.1 核心: Lifecycle Components
这套架构最核心的就是生命周期组件,:Lifecycle Components 用于管理 UI 控制器 (Activity/Freagment) 的生命周期, 方便查询当前组件生命周期的状态.
可查询的状态如下:
具体的使用方式有两种:
继承 LifecycleActivity/LifecycleFragment 即可
自己实现 LifecycleRegistryOwner 接口
- java
- // 通过继承, 就已经将自己的生命周期的交给了 Lifecycle Components 管理了.
- publicclassMainActivityextendsLifecycleActivity{
- }
那我们如何使用呢?
// 通过继承 LifecycleObserver, 保证我们可以通过注解或者接口查询 UI 的生命周期 publicclassMyTestimplementsLifecycleObserver{ privateLifecycle lifecycle; // Lifecycle 包含了当前组件的生命周期 publicMyTest(Lifecycle lifecycle){ lifecycle.addObserver(this); this.lifecycle=lifecycle; } // 当 onResume 发生的时候, 该方法被调用 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) publicvoidresume(){ Log.i("TAG","it called when resume"); } publicvoiddoTest(String s){ // 随时可以查询当前的 UI 状态 if(lifecycle.getCurrentState().equals(Lifecycle.State.RESUMED)){ Log.i("TAG","resume"); }else{ Log.i("TAG","is not resume !!"); } } } publicclassMainActivityextendsLifecycleActivity{ @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 将当前 Activity 的生命周期传递到 MyTest 中即可 MyTest myTest=newMyTest(this.getLifecycle()); } }
看到这里, 你一定心头一喜, 如果有这个组件, 那么我们就完全有能力将 Activity 作为一个 UI 的控制器, 仅仅用来显示 UI 和相应用户操作, 把 Activity 的大小缩小至最小. 不用着急, 大礼包远不止这些.
3.ViewModel 和 LiveData
ViewModel 是一个 UI 相关数据的暂存器, 当所有相关的 UI 都 finish 掉的时候, 它才会清除自己的数据.
LiveData 则是一个持有具体数据并且可被观察, 能感知生命周期的组件(它就像 RxJava 中一个能遵循组件生命周期的 Observable)
他俩的关系, 就是, ViewModel 负责管理着不同的 LiveData, 并把它提供给 UI.
3.1 LiveData
我们可以先来说说 LiveData. 由于它已经能够感知生命周期, 也就意味着我们并不需要在去查询当前 UI 的生命周期, 由于可被观察, 也就意味着当它持有的数据发生改变, 观察者可以立即受到信息. livedata 最重要的方法是一下几个:
onActive()// 当前 LiveData 有超过一个的活跃的观察者时, 被调用 onInactive()// 当前没有任何活跃的观察时, 着被调用 setValue()// 勇于改变当前数据, 这样观察者可以受到改变后的数据. // 观察数据变化, 并感知当前 UI 的生命周期 observe(LifecycleOwner owner, Observer observer)
这里有一个活跃的观察者的概念, 我们不妨把它放在后面来看. LiveData 的用法如下:
publicclassLocationLiveDataextendsLiveData{ privateLocationManager locationManager; privateSimpleLocationListener listener =newSimpleLocationListener() { @Override publicvoidonLocationChanged(Location location){ setValue(location); } }; publicLocationLiveData(Context context){ locationManager = (LocationManager) context.getSystemService( Context.LOCATION_SERVICE); } @Override protectedvoidonActive(){ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0,0, listener); } @Override protectedvoidonInactive(){ locationManager.removeUpdates(listener); } } publicclassMainActivityextendsLifecycleActivity{ @Override protectedvoidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LiveData myLocationListener =newLocationLiveData(); /* * observe(LifecycleOwner owner, Observer observer) * 这个方法就是向 LiveData 中添加观察者, * LiveData 则可以通过 LifecycleOwner 来判断 * 当前传入的观察者是否是活跃的(也就是 UI 是否可见了) */ myLocationListener.observe(this,newObserver() { @Override publicvoidonChanged(@Nullable Location location){ // update // 当 LiveData 中通过 setValue()修改了数据时, // 这里将会受到修改后的数据 } }); } }
好了, LiveData 基本的用法讲完了, 由于有了 LiveData, 我们的 data 更加 "智能" 了. 当 UI 不可见的时候, 改变的数据将不会被更新到 UI 上.
而且如果数据在不同的 UI 界面都会被用到的时候, 我们还可以一个单例的 LiveData, 为不同的 UI 提供统一的数据. 这些操作就不去细讲了.
现在回头看 LiveData, 我们发现它至少有以下几个优点:
可以避免内存泄露: 由于 Observer 和 Lifecycle 绑定, 当 Lifecycle 被销毁后, Observer 自动被清理.
避免在 Activity 被销毁后更新数据导致的崩溃情况
数据可共享
数据更新更智能: 当数据在 UI 不可见的时候更新了, 在恢复可见的时候, 最新的数据会及时更新到 UI 上.
不需要在 Activity 中额外处理生命周期事件
一颗赛艇!
3.2 ViewModel
ViewModel 则相对简单些, 因为他的作用是暂存 UI 相关的数据, 保证即使 Activity 配置更改, 重新创建时, 数据依然能够被保存好.
基本用法如下:
publicclassMyViewModelextendsViewModel{ // MyViewModel 用于管理不同的 LiveData privateMutableLiveData> users; publicLiveData> getUsers() { if(users ==null) { users =newMutableLiveData>(); loadUsers(); } returnusers; } privatevoidloadUsers(){ // do async operation to fetch users } } publicclassMyActivityextendsAppCompatActivity{ publicvoidonCreate(Bundle savedInstanceState){ // 通过了 ViewModelProviders 来获取 ViewModel // 用户获取和 Activity 绑定的 ViewModel MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class); model.getUsers().observe(this, users -> { // update UI }); } }
这是 ViewModel 的最基本的用法, 它负责从各个地方获取数据, 然后把数据装到 LiveData 中, 提供给 UI; 当然 ViewModel 也可以在不同的 Fragment 中共享, 在这里就不多讲了.
由于 ViewModel 的本身和 activity/fragment 的生命周期绑定, 当与之绑定的最后一个 UI 销毁时, ViewModel 才会 clean 自身的数据.
如图所示
4. 数据持久化: Room
Room 是 Google 提供的 SQLite 的 ORM 的解决方案, 其实本质上和其他的 ORM 框架没什么特别大的差别, 没有太多新意, 因此只给出大体的架构图, 有兴趣的同学可以自行去学习
5. 总结
我们现在回头看整个架构
其实最有有趣的就是 UI-ViewModel 这个部分, 这套架构至少可以帮助我们做到一下几点:
UI 与 Data 真正分离
异步调用和逻辑控制可以更加精细(因为对生命周期感知更多)
实现 Model 驱动 UI
想要了解更多 Android 高级知识, 私信[学习] 获取更多资料.
来源: http://www.jianshu.com/p/45ef2ed92d44