Kotlin使用协程简化回调写法

回调机制多使用匿名类来实现,但是写法过于繁琐,很多情况下每使用一次就需要重写一遍匿名类。

第一行代码中HttpURLConnection发送网络请求中使用回调返回给主线程网络请求结果的例子如下:

HttpUtil.sendHttpRequest(address, object: HttpCallbackListener{
    override fun onFinish(response: String){
        //得到服务器返回的具体内容
    }
    override fun onError(e: Exception){
        //处理异常
    }
})

这种写法的缺点就是,有多少网络请求就需要编写多少次的匿名类实现。

Kotlin的协程能够大大简化传统回调的写法。需要使用suspendCoroutine函数

suspendCoroutine函数必须在协程作用域或者挂起函数中才能够调用,它接收一个Lambda表达式参数,主要作用是将当前协程挂起,然后在一个普通的线程中执行Lambda表达式中的代码。

Lambda表达式的参数列表上会传入一个continuation参数,调用它的reusme()方法或reusmeWithException()可以让协程恢复执行。

使用协程简化后的回调写法如下:

suspend fun request(address: String): String {
    return suspendCoroutine{ continuation ->
        HttpUtil.sendHttpRequest(address, object : HttpCallbackListener{
            override fun onFinish(response: String) {
                continuation.resume(response)
            }
            override fun onError(e: Exception){
                continuation.resumeWithException(e)
            }
        } 
    }
}

 request函数是一个挂起函数,函数内部调用了suspendCoroutine函数,这样当前协程就会立刻被挂起,Lambda表达式中的代码则会在普通线程中执行。如果http请求成功,就调用Continuation的resume()方法恢复被挂起的协程,并传入服务器响应的数据,该值就会成为suspendCoroutine函数的返回值。如果请求失败,就调用Continuation的resumeWithException)恢复被挂起的协程,并传入具体的异常原因。

example:

使用retrofit进行网络请求写法(简化前)

val appService = ServiceCreator.create<AppService>()
appService.getAppData().enqueue(object : Callback<App> {
    override fun onResponse(call: Call<List<App>>, response: Response<List<App>>){
        //得到服务器返回的数据
    }    
    override fun onFailure(call: Call<List<App>>, t: Trowable){
        //处理异常
    }
}

 简化后写法:

suspend fun <T> Call<T>.await(): T{
    return suspendCoroutine{ continuation ->
        enqueue(object : Callback<T>{
            override fun onResponse(call: Call<T>, response: Response<T>){
                val body = response.body
                if(body != null) {
                    continuation.resume(body)
                }else {
                    continuation.resumeWithException(RuntimeException(
                        "response body is null"))
                }
            }
            override fun onFailure(call: Call<T>, t: Throwable){
                continuation.resumeWithException(RuntimeException(t))
            }
        })
    }
}

suspend fun getAppData() {
    try {
        val appList = ServiceCreator.create<AppService>().getAppData().await()
        //对服务器响应的数据进行处理
    }catch (e: Exception) {
        //对异常情况进行处理
    }
}

参考:《第一行代码android》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用协程可以让代码更加简洁,易读和易维护。下面是一个使用协程简化回调的示例代码: ```kotlin // 假设我们需要获取用户信息并显示在界面上 suspend fun getUserInfo(userId: String): User { // 发起网络请求获取用户信息,使用挂起函数简化回调 return suspendCoroutine { continuation -> getUserInfoFromNetwork(userId, object : UserInfoCallback { override fun onSuccess(user: User) { // 请求成功,将结果返回给协程 continuation.resume(user) } override fun onError(errorCode: Int) { // 请求失败,将异常返回给协程 continuation.resumeWithException(NetworkException(errorCode)) } }) } } // 在协程作用域中调用 getUserInfo 函数 launch(Dispatchers.Main) { try { val user = getUserInfo(userId) // 将获取到的用户信息显示在界面上 updateUI(user) } catch (e: NetworkException) { // 处理网络请求异常 handleException(e) } } ``` 在上面的示例代码中,我们使用了 `suspendCoroutine` 函数来将回调函数转换为协程挂起函数。在 `getUserInfo` 函数中,我们发起网络请求并通过匿名内部类实现回调接口。当请求成功时,我们通过 `continuation.resume` 函数将结果返回给协程;当请求失败时,我们通过 `continuation.resumeWithException` 函数将异常返回给协程。 在协程作用域中调用 `getUserInfo` 函数时,我们使用 `launch` 函数来创建一个协程,并在其中调用 `getUserInfo` 函数。当协程执行过程中出现异常时,我们可以通过 `try-catch` 语句来捕获异常并进行处理。 使用协程可以让我们将回调函数转换为协程挂起函数,从而简化代码并提高可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值