这篇文章不是用来讲概念的, 只是用来谈论一些关于Android 进程\协程那些问题

1. android 子线程中的异常会引发crash闪退吗?

答案是会的

Thread{throw RuntimeException("this is a error")
}.start()

异常

21741  2379 E AndroidRuntime: java.lang.RuntimeException: this is a error
21741  2379 E AndroidRuntime:   at com.xxxx.app.ui.feed.holder.CommentViewHolder$setComment$1$3$1.run(CommentViewHolder.kt:97)
21741  2379 E AndroidRuntime:   at java.lang.Thread.run(Thread.java:929)

2. android能捕获error"异常"吗

我们知道Exception表示异常, 还有一种是Error, 表示系统严重错误, 他们都继承Throwable.
Exception能被捕获, 那Error能被捕获吗?
答案是可以

try {if (true)throw Error("this is an error")
} catch (e: java.lang.Exception) {logcat("catch by exception")
} catch (e: Throwable) {logcat("catch by throw able")
}

日志如下:

01-20 15:37:56.128  3813  3813 E lklog   : catch by throw able

3. android kotlin协程中异常会引发crash闪退吗?

首先要明确, Android kotlin中的协程是一套线程框架而已, 具体要分为两种情况

3.1 launch中异常会引发闪退吗?

答案是会的

GlobalScope.launch {throw RuntimeException("this is exception")
}

异常

01-20 15:20:05.294 28906  4222 E AndroidRuntime: java.lang.RuntimeException: this is exception
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at com.xxxxx.app.ui.feed.holder.CommentViewHolder$setComment$1$3$1.invokeSuspend(CommentViewHolder.kt:98)
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
01-20 15:20:05.294 28906  4222 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)

3.2 async中异常会引发闪退吗?

答案是不会, 但是在await的时候会抛出异常, 并且异常会抛在await所在的线程

GlobalScope.launch(Dispatchers.Main) {val deferred = GlobalScope.async(Dispatchers.IO) {if (true)throw RuntimeException("this is aysnc exception")true}deferred.await()
}

如上, 我们在IO线程中抛出一个异常, 并且在UI线程中进行await
发生闪退, 日志如下

01-20 15:25:21.254 32198 32198 E AndroidRuntime: java.lang.RuntimeException: this is aysnc exception
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at com.xxxx.app.ui.feed.holder.CommentViewHolder$setComment$1$1$deferred$1.invokeSuspend(CommentViewHolder.kt:70)
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
01-20 15:25:21.254 32198 32198 E AndroidRuntime:    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)

并且可以看到, 进程号和线程号都是32198, 证明异常抛在主线程, 也就是await所在的线程
当去掉await之后, 就可以看到没有异常抛出了
我们顺着async的代码一步一步走过去, 就会发现以下代码

/*** Runs given block and completes completion with its exception if it occurs.* Rationale: [startCoroutineCancellable] is invoked when we are about to run coroutine asynchronously in its own dispatcher.* Thus if dispatcher throws an exception during coroutine start, coroutine never completes, so we should treat dispatcher exception* as its cause and resume completion.*/
private inline fun runSafely(completion: Continuation<*>, block: () -> Unit) {try {block()} catch (e: Throwable) {completion.resumeWith(Result.failure(e))}
}

可以看到异常被捕获了, 所以async是不会有异常抛出的

4. 使用okhttp之后, 网络请求到底在主线程执行, 还是子线程

Android系统规定不能在主线程发起网络请求, 但是我使用okhttp之后, 到底是在哪里发起网络请求的?

  • 同步网络请求, 就在当前线程发起, 如果当前线程是主线程, 就会爆出异常
  • 异步网络请求, okhttp会维护一个线程池, 所以是在子线程中发起的.

主线程同步发起网络请求代码:

val client = OkHttpClient()
val request = Request.Builder().url("http://www.baidu.com").get().build()
val result = client.newCall(request).execute()
val body = result.body()?.string().toString()
logcat("body:$body")

异常

01-20 15:49:03.926  7247  7247 E AndroidRuntime: android.os.NetworkOnMainThreadException
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1565)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at java.net.InetAddress.getAllByName(InetAddress.java:1152)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at okhttp3.Dns$1.lookup(Dns.java:40)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at okhttp3.internal.connection.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:185)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at okhttp3.internal.connection.RouteSelector.nextProxy(RouteSelector.java:149)
01-20 15:49:03.926  7247  7247 E AndroidRuntime:    at okhttp3.internal.connection.RouteSelector.next(RouteSelector.java:84)

主线程异步发起网络请求

val client = OkHttpClient()
val request = Request.Builder().url("http://www.baidu.com").get().build()
client.newCall(request).enqueue(object:Callback{override fun onFailure(call: Call, e: IOException) {logcat("onFail")}override fun onResponse(call: Call, response: Response) {logcat("onResponse")val body = response.body()?.string().toString()logcat("body:$body")}
})

当然不会闪退, 我们深入okhttp的源码看一下

  private boolean promoteAndExecute() {assert (!Thread.holdsLock(this));....for (int i = 0, size = executableCalls.size(); i < size; i++) {AsyncCall asyncCall = executableCalls.get(i);//executorService 返回一个线程池asyncCall.executeOn(executorService());}return isRunning;}

这篇文章管Retrofit什么事

okhttp+retrofit应该是目前Android上最流行的搭配之一

retrofit本质上就是用动态代理的方法来封装了okhttp的网络请求

注, 至于是同步网络请求还是异步网络请求, 和返回值类型有关系, 目前返回Observer(RxJava)和Deferred(kotlin)的是异步网络请求

看一下源码, 这是Retrofit中的OkHttpCall类

  @Override public synchronized Request request() {//同步网络请求okhttp3.Call call = rawCall;if (call != null) {return call.request();}....}@Override public void enqueue(final Callback<T> callback) {checkNotNull(callback, "callback == null");... 异步网络请求call.enqueue(new okhttp3.Callback() {}...}

Android Kotlin okhttp Retrofit 线程协程那些事相关推荐

  1. Kotlin学习笔记21 协程part1 基本概念

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 本节先介绍协程的相关概念 概念可能枯燥,我们先要了解协程中的相关概念 然后结合代码理解这些概念 加深印象 协程的定义 协程 ...

  2. Kotlin开发利器之协程

    Kotlin开发利器之协程 协程的定义   协程的开发人员 Roman Elizarov 是这样描述协程的:协程就像非常轻量级的线程.线程是由系统调度的,线程切换或线程阻塞的开销都比较大.而协程依赖于 ...

  3. Kotlin Jetpack 实战: 图解协程原理 | 开发者说·DTalk

    本文原作者: 朱涛,原文发布于: 朱涛的自习室 https://mp.weixin.qq.com/s/fN4cSg6jcFZo3Wb2_xcJVw 协程 (Coroutines),是 Kotlin「最 ...

  4. 《Kotlin 程序设计》第十二章 Kotlin的多线程:协程(Coroutines)

    第十二章 Kotlin的多线程:协程(Coroutines) Kotlin 1.1 introduced coroutines, a new way of writing asynchronous, ...

  5. 简要说明__python3中的进程/线程/协程

    多任务可以充分利用系统资源,极大提升程序运行效率,多任务的实现往往与 多线程,多进程,多协程有关 稳定性: 进程 > 线程 > 协程 系统资源占用量:进程 > 线程 > 协程 ...

  6. 线程/协程/异步的编程模型(CPU利用率为核心)

    最近看了一个b站博主的视频https://www.bilibili.com/video/av64066246/讲到了线程/协程/异步的编程模型,这里做下记录 1.线程 上篇文章有聊到进程和线程的关系, ...

  7. Linux的进程/线程/协程系列4:进程知识深入总结:上篇

    Linux的进程/线程/协程系列4:进程/线程相关知识总结 前言 本篇摘要: 1. 进程基础知识 1.1 串行/并行与并发 1.2 临界资源与共享资源 1.3 同步/异步与互斥 1.4 进程控制原语 ...

  8. linux的进程/线程/协程系列5:协程的发展复兴与实现现状

    协程的发展复兴与实现现状 前言 本篇摘要: 1. 协同制的发展史 1.1 协同工作制的提出 1.2 自顶向下,无需协同 1.3 协同式思想的应用 2. 协程的复兴 2.1 高并发带来的问题 2.2 制 ...

  9. linux的进程/线程/协程系列3:查看linux内核源码——vim+ctags/find+grep

    linux的进程/线程/协程系列3:查看linux内核源码--vim+ctags/find+grep 前言 摘要: 1. 下载linux内核源码 2. 打标签方法:vim+ctags 2.1 安装vi ...

最新文章

  1. QEMU支持的网络模式
  2. 【Java集合系列四】HashSet和LinkedHashSet解析
  3. 如何使Putty会话颜色更美观
  4. html5 - canvas
  5. 使用 MQTTnet 快速实现 MQTT 通信
  6. AE学习笔记——第一章:AE的界面布局和基本操作
  7. GARFIELD@09-11-2004
  8. 作为企业创业者的老板,只要把这十八个方面做正确就好
  9. Python:提高pip安装速度的网站
  10. python em和web_Python web 框架
  11. python3学习笔记(4)_function-参数
  12. oauth2 token为空拦截_OAuth2 Token 一定要放在请求头中吗?
  13. [MAR DASCTF明御攻防赛]enjoyit_1
  14. Hilbert曲线介绍以及代码实现
  15. 企业网络中的防火墙旁挂实例
  16. MVC与MVVM区别
  17. JavaSE学习之路:Idea小技巧一键生成标准JavaBean(一键生成构造方法和Setter和Getter方法)
  18. reduce函数详解以及自己实现一个reduce函数
  19. 记一次升级Flutter SDK失败的光辉历史
  20. 李兴华java8 课堂笔记_李兴华Java8课堂笔记

热门文章

  1. Python全栈工程师(15:Socket编程4-paramiko模块和SSH秘钥)
  2. Mendix低代码平台,唯快不破
  3. 农业无人机的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  4. pads-logic
  5. python在windows和linux系统下批量读取grib2数据
  6. linux服务开机自启动
  7. CornerNet: Detecting Objects as Paired Keypoints论文笔记(详细)
  8. mac性能比服务器好,性能上再次交锋 三大最新OS测试大比拼
  9. 广州、深圳NPDP认证考试取消通知
  10. python学习之路0x00