1、Android Jetpack 为何出现
服务端以及前端都有一些为人熟知的开发框架,比如服务端的以前的 Spring MVC 以及现在的 SpringBoot,还有前端的 Vue 等等,但是 Android 却很少出现一个广泛被大家使用的开发框架,如果非得说一个被大家用的最多的框架,那可能还就是 MVC 了,而 MVC 或许是最不是框架的框架了,因为即使用了它,代码依旧是臃肿不堪,耦合严重,并没有提升我们的开发效率。即使后来出现了 MVP 以及 MVVM,不过好像也并没有被大家广泛使用起来,而 Google 在这方面也一直没有出一套规范出来,告诉大家什么是正确的方向,什么是他们推荐的开发方式。所以一直以来很多开发者都是按照自己的喜好来写,怎么方便怎么来,怎么快怎么来,各写各的,或许这么来的方式是挺简单的,但是另外别人来接手的时候就麻烦了。可能 Google 也是看到这方面的问题,也想要出一套标准的开发框架,所以 Jetpack 应运而生。
2、Android Jetpack 是什么
关于 Jetpack 的定义,Android 开发者官网已经说得很清楚了,引用如下:“Jetpack 是一套库、工具和指南,可帮助开发者更轻松地编写优质应用。这些组件可帮助您遵循最佳做法、让您摆脱编写样板代码的工作并简化复杂任务,以便您将精力集中放在所需的代码上。”
简而言之就是 Google 要给广大 Android 开发者定规范了,而定这个规范的目的也是为了让开发者可以专心于自己的业务代码上,而不用写那些样板代码,例如后台任务以及生命周期管理等等,如果大家了解过 kotlin 也会发现,使用 kotlin 来开发会让开发者觉得写代码这件事儿变简单了,因为 kotlin 已经为开发者做了各种的封装,开发者需要的时候直接调用就好了,不用再自己吭哧吭哧写 Google 口中的样板代码了,哈哈,小胖突然想到了傻瓜相机,以后会不会出现傻瓜开发框架呢?
所以 Android Jetpack 就是一套可以帮助咱们广大开发者把代码写的更简单更规范的开发框架。
3、Android Jetpack 包含什么
它主要包含四大模块,「基础」「架构」「行为」「界面」,其中每一个里面又包含了若干个小项,小胖对于 Jetpack 的学习是从「架构」这一块开始的,当然的其他的也很重要,小胖以后肯定也会学习了解到的。
其中「架构」里面包含了数据绑定(Data Binding)、Lifecycles(关于 activity 以及 fragment 的生命周期)、LiveData(用于更新界面的数据,跟大家之前理解的 model 不一样,它可以感应生命周期)、Navigation(关于 APP 内的导航跳转)、Paging(可以理解为分页加载)、Room(原来有很多第三方的数据库 ormlite 之类的,现在 Google 出手了,这是对 sqlite 数据库的进一步封装)、ViewModel(前面说了 LiveData,而 ViewModel 就是用来管理 LiveData 的,用于连接 view 视图层和 LiveData 数据层,更重要的是它可以感应声明周期)、WorkManager(用于管理后台任务)。
4、「架构」之 Lifecycles
我们之前的 MVC 最大的缺陷就是让视图层也就是 Activity 以及 Fragment 太重了,所以这次的架构模块的工作之一就是给视图层减轻负担,而 Lifecycles 就是要在视图层的生命周期方面减轻他们的负担,同时也是在减轻我们的负担。我们总避免不了在 Activity 或者 Fragment 的生命周期中做一些事情,好比我们在 Activity 中的 onCreate 里面注册一个服务,然后在 onDestroy 里面解除注册,但是把这部分代码写在 onCreate 子类的生命周期方法中本身就是一种耦合,并且可维护性很差,有了 Lifecycles 这一切都好办了,我们可以把这部分本该写在对应生命周期中的代码写在别的地方了,甚至都不用写在 Activity 以及 Fragment 里,惊不惊喜,意不意外?
Lifecycle 就是一个可以提供 Activity 以及 Fragment 生命周期变化信息的类,并且允许其他对象订阅这些信息。而 Lifecycle 是通过 Event 和 State 来达到这种效果的,其中 Event 是 Lifecycle 发送出来的关于生命周期变化的事件,而 State 则是可以用来判断当前 Lifecycle 处于哪个生命周期阶段,如果把 State 比作一条线上的一个个节点,那么 Event 就是某两个节点之间的状态。
LifecycleObserver 是一个可以监测生命周期变化的类,我们可以通过注解例如 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) 就代表对应视图的 onResume 生命周期方法回调的时候被这个注解所注解的方法就会被调用,当然 Lifecycle.Event 这个枚举类里面还有很多其他的生命周期枚举,基本对应了 Activity 的生命周期方法。
但是只有 LifecycleObserver 监测类还不够呀,还得有视图层被监控,毕竟我们写这个 observer 也是为了监听视图层例如 Activity 生命周期的变化嘛,为了达到这一目的,此时 LifecycleOwner 出现了,而 LifecycleOwner 又是什么呢?
可以认为 LifecycleOwner 就是一个将 Activity 这类视图的生命周期方法暴露出去的类,它将 Activity 和我们前面说的 observer 类联系了起来,一般情况下我们还需要 implements LifecycleOwner,不过 Activity 以及 Fragment 已经帮我们实现好了,我们不用再显示实现了,当然了前提是 Support Library 26.1.0 以及其以上。但是如果自己非得脱离于 Activity 或者 fragment 使用这套生命周期感应组件,那就得必须自己实现 LifecycleOwner 了,同时还得自己负责发送对应的 state 以及 event 出去了,一般情况下我们用不到这些。
看了 Lifecycles 是不是觉得还不错呀,但是如果只是有这么点分离生命周期的功能还是不那么让人满意呀,其实 Lifecycles 功能当然不止于此,它可是 我们下面要讲的 ViewModel 以及 LiveData 的基础,而 Lifecycles 与这两者结合起来后才会发挥出它的真正的神奇功效。接下来就让我们看看吧。
5、「架构」之 ViewModel
我们知道一切新事物的都是为了解决一些问题的,ViewModel 亦是如此,我们之前在开发的时候总会遇到一些数据丢失的问题,好比 Activity 或者 Fragment recreate 了,那么咱们之前界面上的数据一般就丢失了,一些数据可能可以再从网络获取,当然这依然是需要花费用户时间的,如果这个用户还可以忍受的话,那么如果是用户操作出来的数据丢失了,用户可能就需要再次操作一遍,这对用户来说很不友好。
最常见的导致界面重建数据丢失的情况就是 configuration 发生变化的时候,例如发生了横竖屏切换,用户更改了系统的语言等等操作,之前为了应对这种情况我们可能会在 onSaveInstanceState() 方法里面保存一些数据,然后 Activity 重新创建的时候恢复数据,但是这种方式也只能用于存储和恢复一些简单的数据,并且这个数据还得支持序列化和反序列化,这就对我们的业务有了很大的限制,如果遇到大量的数据这种方式就无能为力了。
另外我们需要知道的是即使使用了上述的方法,其实还是在 Activity 层面做事,这不也是在加重 Activity 视图层的负担吗?本来人家视图层只负责视图的渲染、用户的操作响应等等操作就好了,而现在人家还得处理这些数据逻辑,来做自己本不该做的事情,着实是不太合适,最重要的是这会让 Activity 变得臃肿,很难维护,而对于我们写单元测试来说也变得困难。如果到这里一切都结束了,这会是个悲伤的故事,可是 ViewModel 出现了,它的出现就是为了解决我们说的这些问题,从此再也不怕横竖屏切换数据丢失的问题啦。它不仅能解决以上问题,更重要的是还可以帮我们做到数据和 UI 分离,让我们对于数据的处理脱离视图层,这不正好给 Activity 视图层减轻了负担吗?
所以一句话总结就是我们可以认为 ViewModel 就是来帮我们管理视图层需要用到的数据的。说到这里可能会有人疑惑说 Activity 都重建了,那人家的生命周期也发生了对应的变化,如果说 ViewModel 能够保证数据比丢失,那 ViewModel 的生命周期不得比一个 Activity 长呀,的确是如此,在 Activity 或者 Fragment 初次创建的时候,我们可以获取到 ViewModel 实例,而当例如屏幕旋转之类的造成的 Activity 的重建,我们获取到的 ViewModel 实例还是同一个,直到用户退出了这个 Activity,这个 Activity 被 finished 和 destroyed 了。
其实在关于视图层和数据层之间还有一个问题就是数据共享,我们很多时候都有需求就是要在不同的 Fragment 之间共享同一份数据,之前常见的做法就是利用接口回调让多个 Fragment 共享一份可能被各自都操作的数据,而做这种绑定的时候,进行接口回调的时候我们还需要关心回调到的 Fragment 是否存在,不存在了再回调就会发生异常,总之就是这种方式处理起来特别麻烦。而上面我们说了 ViewModel 在 Activity 由于 configuration 发生变化的时候依然能够保证界面获取到的是同一个实例,那么在同一个 Activity 上面的 Fragment 是不是这样呢?更是如此了,并且在依附于同一个 Activity 之上的 Fragment 里面可以获取到同一个 ViewModel 实例,这就完美的解决了数据共享的问题。
6、「架构」之 LiveData
上面说了 ViewModel 是用来管理视图层所需的数据的,是数据层和视图层的一种连接,所以 ViewModel
本身并不负责生产数据,它只是数据的搬运工、处理器而已。那么 ViewModel 处理的数据如何让视图层用到呢?
ViewModel 是独立于视图层而存在的,那通过接口回调的方式把数据回调到视图层?这不行,太麻烦了。
那把需要赋值的视图传递到 ViewModel 里面?这更不行了,这不又让数据和视图层耦合起来了么?这样 ViewModel
还可能会持有视图层对象,而我们知道 ViewModel 的生命周期是会比视图层长的,极有可能发生内存泄漏。此时就该
LiveData 出场了,因为它可以完美的解决这个问题。
LiveData 是一个可以被 observer 的数据,还是一个 awareness 的数据实体,observer 就是可以被监测的,
意思就是如果视图层使用了 LiveData,那么当数据发生变化的时候,是可以直接响应到视图层的,跟我们的设计模式
里面的观察者模式类似,而 awareness 更准确的说是生命周期感应,如果说 viewmodel 对于生命周期的感应是在它比
视图层拥有更长的生命周期的话,那么 LiveData 则是对于生命周期中的 active 以及 inactice 有更多的感应,
咱们上面说了 ViewModel 跟视图层数据连接的问题,其实 LiveData 就是在 ViewModel 被管理的,而 Activity 等视图层
可以通过 ViewModel 获取到 LiveData,而 LiveData 又是可以被观察的,所以它自己的数据有变化又会及时的回调回来,
这样就真的达到了视图与数据的分离,视图层只负责展示不用管数据怎么来,由于视图层和数据层互相之间不强依赖,不耦合,所以也不用担心。内存泄漏的问题。更关键的是 LiveData 是可以感应生命周期的,所以它只会在视图层处于 active 也就是活跃状态的时候才会把数据。响应到视图层,这就避免了视图层被销毁了,或者处于后台的时候我们还往视图层发送数据。
下面再把官网说的使用 LiveData 的好处跟大家同步下:
确保 UI 层和数据状态相匹配:当视图层的生命周期变化的时候,好比从 inactive 变为了 active 状态,LiveData 会把最新的数据
传递到数据层,而从 active 变为 inactive 则会停止向视图层更新数据;
没有内存泄漏的情况:因为当 Activity destroyed 的时候,视图层与数据的 observer 关系会被解除;
不会由于 Activity 等销毁了发生崩溃的情况;
不用处理多余的视图生命周期方面的事情;
总是能够获取到最新的数据:因为 LiveData 会检测 lifecycle 的变化;
能够适配 configuration 的变化:因为 LiveData 是 ViewModel 管理的;
能够共享数据;