黄色的开端
前几天用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()
关于
关于我的Httplib,对Okhttp进行了简单的封装。OnceHttp
对于Request进了简单的封装,对于使用者来说,重点关注入参、出参
出参:无非Response.body
入参:key、value的map或者是bean
一个请求:包括host、api、header、body
使用:
使用前配置
ktHttpConfig(this) {
host = "https://www.wanandroid.com/"
//公共的 header参数
header["appVersion"] = "1.0.0"
//公共的 body参数
//mapData["appVersion"] = "1.0.0"
//可以传入一个client
//okHttpClient = OkHttpClient.Builder().build()
}
复制代码
请求继承 OnceRequest() 就好,api、header、body可以自由更改
OnceRequest,增加了两个拦截的方法
//请求之前 修改 请求的数据
open fun beforeRequest(map:MutableMap<String,String>) = mapData
//请求之后 修改 返回的数据
open fun <T> afterRequest(bean:T) : T = bean
复制代码
在一次请求前,修改参数,在请求后,修改返回的数据。(比如:请求其他服务器,加密解密方式不同)
也提供了3种数据返回方式
requestBackLiveData(): LiveData<T>
requestBackFlow(): Flow<T>
requestBackBean():T
复制代码
内容较多,不是很完善,持续更新中
如果感觉本文内容对你有帮助的话,麻烦点个赞。
如果内容有错误,我及时更改。