如何优雅的结合Retrofit和KT协程

依赖

// Retrofit 依赖
implementation ("com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2")

// Retrofit的一个转换器,使用Gson库来序列化和反序列化JSON数据。
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")

DTO

请求验证码的DTO

data class GetCodeRequestDTO(var phone: String) {
}
data class GetCodeResponseDTO(val code:Int,val msg:String,val data:String) {
}

请求登录的DTO

data class LoginRequestDTO(val phone: String,val smsCode: String) {
}
data class LoginResponseDTO(val code:Int,val msg:String,val data:String) {
}

Api接口

DeferredKotlin 协程中的一种类型,表示一个可能在未来某个时刻完成的计算或异步操作的结果。Deferred 通常用于需要返回结果的异步操作中。

  • await(): 一个挂起函数,用于等待 Deferred 完成并返回结果。如果 Deferred 完成时抛出了异常,await() 会将这个异常重新抛出。
  • cancel(): 可以取消与 Deferred 关联的协程。
interface LoginApiService {
    @POST("weibo/api/auth/login")
    fun requestLogin(@Body loginRequest: LoginRequest): Deferred<LoginResponse>
}
interface GetCodeApiService {
    @POST("weibo/api/auth/sendCode")
    fun requestGetCode(@Body sendCodeRequest: SendCodeRequest): Deferred<GetCodeResponse>
}

Retrofit类

HTTP API转换成Java接口
使用lazy修饰的属性在第一次被访问时才会进行初始化,而不是在创建宿主对象时立即初始化。

import com.jakewharton.retrofit2.adapter.kotlin.coroutines.CoroutineCallAdapterFactory
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClient {
    private const val BASE_URL = "https://XXX.XXX.XXX/"

    // 创建 共享Retrofit 实例
    private val retrofit: Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(CoroutineCallAdapterFactory())
        .build()

    // 创建 GetCodeApiService 的实例
    val getCodeApiService: GetCodeApiService by lazy {
        retrofit.create(GetCodeApiService::class.java)
    }

    // 创建 LoginApiService 的实例
    val getLoginApiService: LoginApiService by lazy {
        retrofit.create(LoginApiService::class.java)
    }

}

协程发送请求

这里以viewLifecycleOwner.lifecycleScope.launch的方式启动协程,viewLifecycleOwner.lifecycleScope.launch结合了 lifecycleScope 的生命周期感知能力和 launch 的协程启动功能,是Android协程编程中推荐的做法之一。
await() Kotlin协程中一个非常重要的挂起函数(suspend function),它用于等待一个异步操作完成。在协程的世界里,await()通常与 Deferred 对象一起使用,正如前面所言,Deferred 是一个代表了未来某个时刻会完成的计算结果的容器。
请求验证码的函数

private fun requestVerificationCode(phoneNumber: String) {
    // 创建了一个新的协程作用域
    viewLifecycleOwner.lifecycleScope.launch { 
        try {
            // 实例化一下传的参数
            sendCodeRequest = SendCodeRequest(phoneNumber)

            // 获取 Retrofit 配置的 API 服务接口实例
            val apiService = RetrofitClient.getCodeApiService

            // 直接在lifecycleScope.launch中调用挂起函数
            val response = apiService.requestGetCode(sendCodeRequest!!).await() // 等待Deferred完成并获取结果
            Log.d(TAG, "requestVerificationCode: $response")
            // 这里可以继续处理响应结果

        } catch (e: Exception) { // 捕获异常,例如网络错误或序列化问题
            Log.d(TAG, "requestVerificationCode: ${e.message}")
            // 这里可以处理异常,例如显示错误信息给用户
        }
    }
}

求登录的函数

// 请求登录
private fun requestLogin(phoneNumber: String,codeNumber:String) {
    // 创建了一个新的协程作用域
    viewLifecycleOwner.lifecycleScope.launch { 
        try {
            // 实例化一下传的参数
            loginRequest = LoginRequest(phoneNumber,codeNumber)

            // 获取 Retrofit 配置的 API 服务接口实例
            val apiService = RetrofitClient.getLoginApiService

            // 直接在lifecycleScope.launch中调用挂起函数
            val response = apiService.requestLogin(loginRequest!!).await() // 等待Deferred完成并获取结果
            Toast.makeText(context, "登录成功", Toast.LENGTH_LONG).show()
            // 这里可以继续处理响应结果

        } catch (e: Exception) { // 捕获异常,例如网络错误或序列化问题
            Log.d(TAG, "requestVerificationCode: ${e.message}")
            // 这里可以处理异常,例如显示错误信息给用户
        }
    }
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
对于Retrofit协程结合,可以通过封装来简化使用和处理异步操作。以下是一个简单的示例: 首先,你可以创建一个协程适配器(CoroutineCallAdapterFactory)并添加到Retrofit的Builder中: ```kotlin val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(CoroutineCallAdapterFactory()) .build() ``` 接下来,你可以定义一个封装了异步操作的协程函数,例如: ```kotlin suspend fun <T> Call<T>.await(): T { return suspendCancellableCoroutine { continuation -> enqueue(object : Callback<T> { override fun onResponse(call: Call<T>, response: Response<T>) { if (response.isSuccessful) { response.body()?.let { continuation.resume(it) } ?: continuation.resumeWithException(NullPointerException("Response body is null")) } else { continuation.resumeWithException(HttpException(response)) } } override fun onFailure(call: Call<T>, t: Throwable) { if (continuation.isCancelled) return continuation.resumeWithException(t) } }) continuation.invokeOnCancellation { try { cancel() } catch (ex: Throwable) { // Ignore cancel exception } } } } ``` 这个函数将一个Retrofit的Call对象转换为一个挂起函数,它会在请求完成时返回结果或抛出异常。 最后,你可以在协程中使用封装后的Retrofit方法,例如: ```kotlin suspend fun fetchData(): List<Item> { val service = retrofit.create(ApiService::class.java) val response = service.getItems().await() return response.items } ``` 这样,你就可以使用协程的方式来发起异步请求并获取结果了。注意,上述代码中的`ApiService`是你自己定义的Retrofit接口。 希望以上示例能对你有所帮助!
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值