你应该知道的 Android 网络访问方式的演化史

栏目: Java · 发布时间: 6年前

内容简介:你应该知道的 Android 网络访问方式的演化史

作者:Elye 编译者:Kotlin之巅

你应该知道的 Android 网络访问方式的演化史

众所周知,Android 不知不觉间已经存在超过 10 年了,与此同时,Android 开发者们访问网络的方式也在不断演化中。本文我将通过一个例子来简单分享我对这个演化的认识。

恐龙时代:直接访问

在 Android 2.2 版本之前,网络访问相关的代码和其他代码一样,可以在主线程中直接使用,不会导致任何异常:

然而,这种用法体验并不理想,因为网络访问相对 UI 交互来说通常很慢,视具体的接口而定,通常需要几秒钟时间,这段时间内 UI 界面会卡住,用户体验比较糟糕。因此,在后面的版本中,如果你在主线程中访问网络,Android应用在运行时将会毫不留情的抛出 NetworkOnMainThreadException 异常,导致应用闪退。

当然也还是有一些办法可以强制 Android 允许在主线程中直接访问网络,就像本文这个例子中一样,但这种操作仅仅用于演示目的,千万不要在任何线上产品中使用。

石器时代:使用子线程

稍微有点经验的开发者应该都知道,为了不阻塞 UI 交互,我们可以把网络访问部分代码放到后台线程中,这样就能够在访问网络获取数据的同时能够有流畅的 UI 响应。示例代码如下所示:

上面的代码是在子线程中访问网络的基本方式,需要注意的一点是,更新 UI 界面的代码必须是放到主线程中,也就是通过使用主线程的 Looper.getMainLooper() 来创建 Handler,否则会出现 CalledFromWrongThreadException 异常。

这种方式有很多不足之处,因为线程的管理通常比较复杂,让开发者直接处理这种线程问题可能会导致写出来的 App 存在出错的风险,因此,Google 做了进一步的优化。

青铜时代:AsyncTask

由于主线程已经禁用直接访问网络,因此,Google 提出了一种推荐的方法,称为 AsyncTask。

AsyncTask 带来了很多不错的特性,例如在后台线程中执行网络请求之前和之后,可以允许我们在主线程执行某些操作,同时,它也支持渐进式的更新等。示例代码如下所示:

曾几何时,这种方式被称为标准的网络访问方式,网络上也能找到相关的教程。

尽管 AsyncTask 是 Google 引入的,但开发者们陆续发现它的一些缺陷,特别是跟 Android 应用生命周期相关的,具体可以参考 The Hidden Pitfalls of AsyncTask 这篇文章。

因此,尽管曾经是标准方式,但现在已经没什么人用它了。

中世纪:IntentService

由于 AsyncTask 不尽如人意,另外一个流行的方式出现了,它就是 IntentService。

当然,IntentService 并不是 Google 专门引入用来解决 AsyncTask 缺点的,它最初是为了后台长时间运行的服务(例如文件下载)而设计的。

随着社区对 AsyncTask 的摒弃,开发者们开始考虑将 IntentService 作为替代方案。

使用简单的代码片段很难讲清楚这种方式,因此我们来看下面这张图。IntentService 位于 Activity 之外,它本质上是一个 Service,需要注册到 AndroidManifest 中。

你应该知道的 Android 网络访问方式的演化史

我们可以把 IntentService 当作一个线程,网络访问代码如下所示:

可以看到,当网络访问完成后,它通过 BroadcastReceiver 发送消息给 Activity 来实现结果信息的传递。

因此,虽然这种方式可以作为替代方案,但相对来说属于重量级的方式,如果我们只是想要发起一个简单的网络请求,这种方式显得太过笨重。

工业时代:RxJava

随着函数式编程和响应式编程的流行,RxJava 也被引入了 Android 社区。

很快的,网络访问的标准方式变成了 RxJava。

这种方式之所以流行,是因为它通过链式调用的方式把主线程和子线程的操作串联起来。

我想如果有人声称自己在使用 RxJava,那么很大可能他只是在项目中网络访问部分的代码中使用 RxJava,其他地方的代码根本就没有使用 RxJava 这种函数响应式编程范式。

这种现象的原因是响应式编程本身是一个相对比较复杂的概念,不好掌握,而且需要使用匿名类(因为当时 Android 开发中只能使用 Java 6 和 Java 7),因此代码写起来并不是很顺畅。

现代:RxJava + Kotlin

2017 年,Google 宣布在 Android Studio 中对 Kotlin 语言提供一级公民形式的支持,这使得使用 Kotlin 开发 Android 迅速流行起来。使用 Kotlin 中的 lambda 表达式代替 Java 中匿名类,使得 RxJava 的使用更加简洁。

让我们来看看实现相同功能的网络访问代码使用 Kotlin 改写后的形式:

可以看到,实现相同功能的代码简练了很多。因此,在 Kotlin 中,RxJava 方式访问网络变得更加流行,出现了越来越多有趣且优雅的使用 RxJava 访问网络的方式。具体可以参考这两篇文章:《RxJava: Clean way of prefetching data and use later》,《Managing Network State using RxJava》。

未来:Coroutines

尽管 RxJava 解决了很多问题,但它的学习曲线对很多初学者来说还是很陡峭的。响应式编程范式对多数使用者来说会显得有点别扭,源头(网络获取的数据)和结果(发送给 UI 界面显示的数据)之间的联系看起来并不直接。

最新版本的 Kotlin 引入了 Coroutines,虽然现在还处于试验阶段,但它看起来前景广阔。

Coroutines 最大的亮点是使得异步代码看起来像同步代码,如下所示:

如果你想代码变得更优雅,例如使用 future 或者 promises 之类的概念使得代码更具响应式的特点,那么也可以通过 async-await 的方式来编写:

因此,在我看来,Coroutines 很好的桥接了初学者社区和资深的专家。这里有一篇不错的文章(《Simple asynchronous loading with Kotlin Coroutines》)将 Kotlin 的 Coroutines 和 Android 的生命周期 API 相结合。结合后代码示例如下:

看起来前景广阔吧,以上是我对未来几个月 Android 网络访问方式的预测,如果你有其他想法,欢迎交流。

参考文档

  1. 原文链接:https://medium.com/@elye.project/the-evolution-of-android-network-access-1e199fc6e9a2

  2. 本文示例代码地址:https://github.com/elye/demo android network_evolution

  3. AsyncTask:https://developer.android.com/reference/android/os/AsyncTask.html

  4. The Hidden Pitfalls of AsyncTask:http://blog.danlew.net/2014/06/21/the-hidden-pitfalls-of-asynctask/

  5. RxJava: Clean way of prefetching data and use later:https://medium.com/@elye.project/rxjava-clean-way-of-prefetching-data-and-use-later-54800f2652d4

  6. Managing Network State using RxJava:https://medium.com/@elye.project/managing-network-state-using-rxjava-79cdaed88d5d

  7. Simple asynchronous loading with Kotlin Coroutines:https://hellsoft.se/simple-asynchronous-loading-with-kotlin-coroutines-f26408f97f46

  8. Android 生命周期 API:https://developer.android.com/topic/libraries/architecture/lifecycle.html


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

趣学算法

趣学算法

陈小玉 / 人民邮电出版社 / 2017-7-1 / 89.00元

本书内容按照算法策略分为7章。 第1章从算法之美、简单小问题、趣味故事引入算法概念、时间复杂度、空间复杂度的概念和计算方法,以及算法设计的爆炸性增量问题,使读者体验算法的奥妙。 第2~7章介绍经典算法的设计策略、实战演练、算法分析及优化拓展,分别讲解贪心算法、分治算法、动态规划、回溯法、分支限界法、线性规划和网络流。每一种算法都有4~10个实例,共50个大型实例,包括经典的构造实例和实......一起来看看 《趣学算法》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试