Kotlin使用协程简化回调写法

本文介绍如何使用Kotlin的协程简化传统回调机制。通过suspendCoroutine函数配合Lambda表达式,可以有效减少代码冗余,提高开发效率。文章提供了一个使用retrofit进行网络请求的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

第一行代码中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》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值