用Kotlin Coroutines和Architecture Components进行Android开发

2017 年 10 月 16 日 移动开发前线 核子可乐 译
作者|Marek Langiewicz
编辑|覃云

开发正在快速发展,众多开发人员与企业都在努力解决各类常见问题,并打造出一系列能够彻底改变我们应用结构的工具或库。

我们对这种新的可能性感到兴奋无比,但却很难真的投入大量时间重新编写原有应用以充分发挥新型编程风格带来的种种潜力。然而,如果我们从全新项目起步,结果又会如何?我们能够向其中引入哪些突破性的思维?哪些解决方案可以带来理想的稳定性?我们是否应该广泛使用 RxJava,并将 响应式至上思路 作为应用的结构指导?

Cycle.js 库 (来自 André Staltz) 对于响应式至上思维作出了很好的诠释: Cycle.js — Streams。

链接:

  • https://medium.com/@andrestaltz

  • https://cycle.js.org/streams.html

Rx 具备良好的可组合特性,因此拥有巨大的发展潜力 ; 然而,其与常规的面向对象编程风格又存在着显著区别。事实上,对于毫无 RxJava 使用经验的开发人员而言,其确实存在着难以理解的问题。

在开始新项目之前,我们面临着更多需要回答的问题。举例来说:

  • 我们应该利用 Kotlin 替代 Java 吗?(简单来讲,答案是 肯定的。)

  • 我们应该使用实验性的 Kotlin Coroutines 吗?(其带来了全新的编程风格。)

  • 我们是否该使用谷歌提供的实验性库:Android Architecture Components?

要为这些问题找到答案,我们需要首先创建一款小小应用,从而做出明智的决定。而这正是本文的内容所在——依托于整个流程得出有用的见解。如果大家希望了解更多细节,咱们马上进入主题。

关于这款应用

这次实验的目标在于创建一款应用,其能够下载用户所选定城市的相关天气数据,并将预报结果通过图形化图表的形式显示出来(再配上一些酷炫的动画)。要求很简单,但其中已经囊括了各类 Android 项目中会涉及到的大多数功能。

事实证明,coroutinesarchtiecture components 确实能够良好协作,并给我们带来能够顺利解决大量问题的整洁应用架构。

Cortoutines 帮助我们以自然简洁的方式表达思路。如果大家希望代码能够逐行体现您所希望执行的确切逻辑(即使您可能也需要在其间进行一些异步调用),suspendable 函数也能很好地完成任务。

另外需要强调的是:无需在回调之间往来跳转。在本示例应用当中,coroutines 还彻底消除了对 RxJava 的依赖性。配合 suspendable 点的各函数在阅读及理解难度方面远低于部分 RxJava 运算符链——这些链可以快速实现函数化转换。

话虽如此,但我个人认为并不是在每个用例中都能将 RxJava 替换为 coroutines。我们发现,observalbes 就是一类无法被逐一映射为 suspendable 函数的表达类型。特别是如果 observable 运算符链允许多个事件从其中流经,且其中每个 suspendable 点只能在每次调用时恢复一次,则无法实现一对一映射。

回到我们这款天气应用中来:您可以查看其运作效果——但请注意,我并不是设计师,所以相关成果可能比较简陋。图表动画显示您能够轻松利用简单的 cortoutine 以手动方式加以实现——其中不涉及任何 ObjectAnimators、Interpolators、Evaluators 或者 PropertyValuesHolders 等等。

最重要源代码片段已经展示如下。不过如果您希望查看完整项目,请参阅 GitHub。

  • GitHub:

https://github.com/elpassion/crweather

代码量并不大,相信大家能够轻松完成浏览。

我将从网络层开始介绍这款应用的具体结构。接下来,我会探讨业务逻辑(在 MainModel.kt 文件中),其几乎不受限于 Android 系统平台。最后,则是 UI 部分(这显然仅适用于 Android 系统)。

  • MainModel.kt :

https://github.com/elpassion/crweather/blob/master/app/src/main/java/com/elpassion/crweather/MainModel.kt

为了方便起见,我在这里为总体架构图添加了文本参考编号。我会特别关注其中 绿色 元素——即 suspendable 函数与 actors(一个 actor 实际上就是一种非常实用的 coroutine builder)。

总体来讲,actor 模型属于一种并行计算数学模型——我将在下一篇博文中就此展开详细探讨。

01 天气服务

这项服务负责从 Open Weather Map REST API 处下载特定城市的天气预报数据。

  • Open Weather Map REST API :

    http://openweathermap.org/api

在这里,我使用了一套来自 Square 的简单但强大的库——Retrofit。我猜如今的 Android 开发人员不会没听说过它,但对于那些尚未接触过的朋友,这里再解释几句:这是一套非常流行的 Andoird 平台 HTTP 客户端。其能够面向 POJO 执行网络调用与响应解析。这里我们直接使用典型的 Retrofit 配置。我还插入了 Moshi 转换器将 JSON 响应转换为数据类。

  • Retrofit : http://square.github.io/retrofit/

  • POJO : https://en.wikipedia.org/wiki/Plain_old_Java_object

  • Moshi : https://github.com/square/retrofit/tree/master/retrofit-converters/moshi

这里需要强调的一点是,我将由 Retrofit 生成的函数类型返回至另一新函数: Call。

我利用 Call.enqueue(回调) 以面向 Open Weather Map 实际执行调用。这里我并没有使用由 Retrofit 提供的任何调用 适配工具,这是为了保证自己能够将 Call 对象打包在 suspendable 函数当中。

  • Call : https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Call.java

  • Call.enqueue : https://github.com/square/retrofit/blob/b3ea768567e9e1fb1ba987bea021dbc0ead4acd4/retrofit/src/main/java/retrofit2/Call.java#L48

  • 适配工具

    https://github.com/square/retrofit/tree/master/retrofit-adapters

02 实用工具

从这里,我们正式迈入了 全新的 coroutines 世界:我们希望创建一条打包有 Call 对象的 suspendable 函数

要完成这部分内容,您需要掌握 coroutines 的一部分基础知识。如果您尚不了解,请参阅 《Coroutines 指南》 的第一章内容(由 Roman Elizarov 撰写)。

  • 《Coroutines 指南》 :

https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md

这将是一条扩展函数:suspend fun Call . await(),其负责调用 Call.enqueue(…)(以实际执行网络调用),而后调用 suspends,再然后是 resumes(当响应返回时)。

要将任意异步计算转化为 suspendable 函数,我们需要使用 The Kotlin 标准库当中的 suspendCoroutine 函数。其能够为我们提供一个 Continuation 对象,这属于一类通用回调。我们只需要在对新的 suspendable 函数进行恢复时(通常是在出现异常的情况下),调用其 resume 方法(或者 resumeWithException 方法)即可。

下一步是使用我们的新 suspend fun Call . await() 函数,其负责将由 Retrofit 生成的异步函数转换为便捷的 suspendable 函数

  • suspendCoroutine 函数

https://github.com/JetBrains/kotlin/blob/8f452ed0467e1239a7639b7ead3fb7bc5c1c4a52/libraries/stdlib/src/kotlin/coroutines/experimental/CoroutinesLibrary.kt#L89

  • Continuation 对象:

https://github.com/JetBrains/kotlin/blob/8fa8ba70558cfd610d91b1c6ba55c37967ac35c5/libraries/stdlib/src/kotlin/coroutines/experimental/Coroutines.kt#L23

  • resume 方法

https://github.com/JetBrains/kotlin/blob/8fa8ba70558cfd610d91b1c6ba55c37967ac35c5/libraries/stdlib/src/kotlin/coroutines/experimental/Coroutines.kt#L32

  • resumeWithException 方法:

https://github.com/JetBrains/kotlin/blob/8fa8ba70558cfd610d91b1c6ba55c37967ac35c5/libraries/stdlib/src/kotlin/coroutines/experimental/Coroutines.kt#L38

03 Repository

Repository 对象属于我们在应用中需要显示的数据(图表)的实际来源。

在这里,我们会使用一些由 suspend fun Call . await() 扩展生成的专用 suspendable 函数,用以实现天气服务功能。如此一来,其返回的将全部为可立即使用的 Forecast 预报等数据,而非 Call 。接下来,我们在一条公共 suspendable 函数 中使用这些数据:suspend fun getCityCharts(city:String):List 。其能够将来自 API 的数据转化为可随时显示的图表清单。这里我使用 List 上的部分定制化扩展属性以将数据实际转换至 List 。需要强调的是,只有 suspendable 函数能够调用其它 suspendable 函数

为了简单起见,我们这里对此 appid 进行硬编码。如果大家希望对应用进行测试,请点击此处生成新的 appid——这是因为如果此硬编码 appid 被多人频繁使用,则会自动被屏蔽 24 小时。

在下一步中,我们将创建主应用 模型(采用 Android ViewModel 架构组件),其利用一个 actor(coroutine builder) 以实现应用逻辑。

  • ViewModel :

https://developer.android.com/topic/libraries/architecture/viewmodel.html

 04 模型 

在这款应用中,我们只使用一套简单的模型: MainModel : ViewModel,且仅供一种活动使用: MainActivity

这个类代表着应用本身。其将由我们的活动(实际上是由 Android 系统的 ViewModelProvider)进行实例化,但能够在配置变更(例如屏幕旋转)后继续存在,且保证新的活动实例仍拥有相同的模型实例。我们完全不必担心活动生命周期问题。相较于实现与各方法(onCreate、onDestroy 等)相关的活动生命周期,这里我们只拥有一项 onCleared() 方法,其会在用户退出此应用时进行调用。更确切地讲,当活动 finished 时,onCleared 方法将得到调用。

  • ViewModelProvider:

https://developer.android.com/reference/android/arch/lifecycle/ViewModelProvider.html

更确切地讲,当活动 finished 时,onCleared 方法将得到调用。

尽管并没有与活动生命周期紧密结合,我们仍然需要采取某种方式以发布应用模型的当前状态,从而将其显示在某些特定位置(在活动中)。在这方面,LiveData 能够发挥良好作用。

LiveData 类似于对 RxJava BehaviorSubject 的二次创造……其拥有一项 observable 可变值。其最重要的差异体现在订阅方式以及随后在 MainActivity 当中进行查看的方式上。

  • LiveData:

https://developer.android.com/topic/libraries/architecture/livedata.html

  • RxJava:

https://github.com/ReactiveX/RxJava

  • BehaviorSubject :

https://github.com/ReactiveX/RxJava/wiki/Subject

  • MainActivity :

https://github.com/elpassion/crweather/blob/master/app/src/main/java/com/elpassion/crweather/MainActivity.kt

不过 LiveData 也不具备像 Observable 那样强大的可组合运算符。大家可以 查看 LiveData 提供的部分简单转换信息。

不过 LiveData 也不具备像 Observable 那样强大的可组合运算符。大家可以点击此处查看 LiveData 提供的部分简单 转换信息。

另一项区别在于,LiveData 仅适用于 Android,但 RxJava 主题则更具普适性 ; 因此我们可以利用常规非 Android JUnit 对后者进行轻松测试。

最后一项不同是,LiveData 具有“生命周期意识”——我将在下一篇介绍 MainActivity 类的博文当中对此作出详尽探讨。

在本示例中,我们选择使用 MutableLiveData:各 LiveData 对象允许直接向其中随意添加新值。应用 state 由 4 个 LiveData 对象负责体现:city、charts、loading 以及 message。其中最重要的自然是 charts:LiveData<list ></list 对象,其代表着需要显示的当前图表清单。

所有会引发应用状态变化以及响应用户操作的任务皆由 ACTOR 负责执行。

Actors 非常强大,我将在下一篇博文中进行具体解释。

  • MutableLiveData :

https://developer.android.com/reference/android/arch/lifecycle/MutableLiveData.html

    总结   

我们已经为主 actor 作好了一切筹备。如果大家认真查看 actor 代码内容,那么即使您并不了解 coroutines 或者 actors 理论,应该也能够看懂其工作原理。虽然只有寥寥数行,但其中实际包含着本款应用的全部重要业务逻辑。最值得强调的就是我们调用 suspendable 函数 的位置(由绿线加灰色箭头所指定的部分)。第一个位置为 suspendable 点,即随用户操作进行迭代的部分 ; 第二个位置则为网络调用。归功于 coroutines,这里的内容更近似于同步阻塞代码,但实际上却并不会拥塞该线程。

请大家期待我的下一篇博文,届时我将详细讲解关于 actorschannels 的一切。

原文链接:

https://blog.elpassion.com/create-a-clean-code-app-with-kotlin-coroutines-and-android-architecture-components-f533b04b5431

活动推荐:

Google 如何用 AI 造聊天机器人?Pinterest 如何用机器学习获得两亿活跃用户?10 月 QCon 上海站,还有来自 Uber、Paypal、LinkedIn、Airbnb 等顶尖技术专家前来分享前沿实践经验。

QCon 报名即将结束,识别下方二维码或点击【阅读原文】与 100+ 国内外技术大咖零距离,如有问题欢迎联系票务经理 Hanna ,电话:15110019061,微信:qcon-0410。




登录查看更多
0

相关内容

一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库。
FPGA加速系统开发工具设计:综述与实践
专知会员服务
63+阅读 · 2020年6月24日
专知会员服务
31+阅读 · 2020年4月24日
Java开发者必看!机器学习开发库精选
云栖社区
5+阅读 · 2018年8月22日
干货 | AutoML 和神经架构搜索初探
AI科技评论
3+阅读 · 2018年8月1日
刚开始学编程?这几款小工具能让你事半功倍
你知道量子计算吗?它超酷的!
微软研究院AI头条
4+阅读 · 2018年3月16日
这几本Python新书特别赞
图灵教育
19+阅读 · 2018年3月1日
免费云真机测试 | 让您的应用完美适配 Android Oreo
引力空间站
3+阅读 · 2018年2月2日
码农日常工具推荐
架构文摘
4+阅读 · 2017年9月26日
Arxiv
10+阅读 · 2019年1月24日
Neural Architecture Optimization
Arxiv
8+阅读 · 2018年9月5日
Zero-Shot Object Detection
Arxiv
9+阅读 · 2018年7月27日
Arxiv
3+阅读 · 2018年6月24日
Arxiv
4+阅读 · 2018年3月19日
VIP会员
相关资讯
Java开发者必看!机器学习开发库精选
云栖社区
5+阅读 · 2018年8月22日
干货 | AutoML 和神经架构搜索初探
AI科技评论
3+阅读 · 2018年8月1日
刚开始学编程?这几款小工具能让你事半功倍
你知道量子计算吗?它超酷的!
微软研究院AI头条
4+阅读 · 2018年3月16日
这几本Python新书特别赞
图灵教育
19+阅读 · 2018年3月1日
免费云真机测试 | 让您的应用完美适配 Android Oreo
引力空间站
3+阅读 · 2018年2月2日
码农日常工具推荐
架构文摘
4+阅读 · 2017年9月26日
相关论文
Top
微信扫码咨询专知VIP会员