黄色的开端
前几天用Okhttp的时候写了一个请求,代码突然变黄了。通常来说会这样写,就算封装也离不开4步
withContext(Dispatchers.IO){
val client = OkHttpClient.Builder().build()
val request = Request.Builder().build()
client.newCall(request).execute()
}
复制代码
但是它突然变黄了
我本以为是IO的警告,加上try、catch还是不行,鼠标一动到黄色位置,提示警告:
Inappropriate blocking method call
黄色的原因
不适当的阻塞方法调用
这是什么意思呢?
首先 协程是封装了一套线程池的api,一段协程代码会在一个线程上运行,多段协程代码也有可能在这个线程上运行,充分利用线程。
不适当的阻塞方法调用,也就是说这段代码,对协程可能会有影响,从而导致多个协程任务,在一个线程上运行,变成了 这个任务在一个线程上运行。不完全利用。
探索黄色
okhttp点进去看
@Throws(IOException::class)
fun execute(): Response
fun enqueue(responseCallback: Callback)
复制代码
原来抛出了IOException。
猜想,try、catch不能清除黄色,那么肯定更异常没关系。写了一个方法,修改抛出的异常
@Throws(NullPointerException::class)
fun execute() {
}
复制代码
结果只有IOException会这样。
就4行代码,肯定和协程有关。
既然是协程,又是IO问题,看了一眼IOException类,又点了一下,看看继承IOException,被60多个类继承了。
看到了SocketException,突然想到,Socket也是一个IO操作,假设Socket连上了,然后阻塞在了这里,如果Socket突然断开了,通常会try、catch,关闭Socket。
那就是说这个http正在请求,进行IO操作,突然断开,只要把请求关了就行。
再换个比方说:
withContext(Dispatchers.IO){
//...
IO操作
//...
}
复制代码
在协程里有个请求,协程不知道它IO操作要多久,假设IO他一直在执行,那协程可能就单独放到一个线程执行,一直阻塞。这不能发挥 协程的 真正作用。所以编译器提示了警告:这个阻塞不太适当
解决黄色
原因:协程认为可能抛出IO异常的代码,可能会一直阻塞,把代码放到线程执行。
协程就是处理耗时任务,只是不想浪费资源。所以 我们期望都在协程上执行。
解决:把代码 丢到一个可取消的协程上执行
val response = suspendCancellableCoroutine<Response> {
client.newCall(request).execute()
}
复制代码
表示这段代码可以被取消。成功则返回Response,失败则取消这个协程。关于异步同样可以使用call.cancel()
如果内容有错误,我及时更改。