如何在Kotlin中使用await等待Retrofit网络请求?
实现Retrofit请求的
await()调用方式 完全可以实现你想要的调用形式,但需要注意**await()是Kotlin协程的挂起方法,不能直接在主线程的非挂起函数(比如onCreate)中调用**,必须在协程作用域内执行。下面是具体实现步骤和代码示例:
1. 添加必要依赖
在项目的build.gradle(Module级别)中添加Retrofit、协程相关依赖:
// Retrofit核心 implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Gson解析器 implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Retrofit协程适配(用于支持Deferred返回类型) implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' // Android协程核心 implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' // Lifecycle协程作用域(用于Activity/Fragment安全启动协程) implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.1'
2. 定义Retrofit接口
有两种写法适配协程调用:
// 数据实体类 data class User(val id: Int, val name: String) interface UserApi { // 写法1:返回Deferred,支持调用await()获取结果 @GET("users") fun getUsersDeferred(): Deferred<List<User>> // 写法2:直接用suspend函数(Retrofit 2.6+推荐写法,更简洁) @GET("users") suspend fun getUsers(): List<User> }
3. 封装Repository层
class UserRepository(private val userApi: UserApi) { // 对应写法1,返回Deferred对象 fun getUsersDeferred(): Deferred<List<User>> { return userApi.getUsersDeferred() } // 对应写法2,挂起函数 suspend fun getUsers(): List<User> { return userApi.getUsers() } }
4. 在Activity中调用
必须在协程作用域内执行挂起方法,这里用官方推荐的lifecycleScope(自动跟随Activity生命周期取消协程):
class MainActivity : AppCompatActivity() { private lateinit var userRepository: UserRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 初始化Retrofit实例 val retrofit = Retrofit.Builder() .baseUrl("https://你的API基础地址/") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(CoroutineCallAdapterFactory()) // 写法1需要添加此适配器 .build() // 初始化API和Repository val userApi = retrofit.create(UserApi::class.java) userRepository = UserRepository(userApi) // 启动协程执行请求 lifecycleScope.launch { try { // 写法1:调用await()获取结果 val dataFromDeferred = userRepository.getUsersDeferred().await() // 写法2:直接调用挂起函数 val dataFromSuspend = userRepository.getUsers() // 处理获取到的数据 println("用户数据:$dataFromSuspend") } catch (e: Exception) { // 处理请求异常(比如网络错误、解析错误) e.printStackTrace() } } } }
关键注意点
- 不能直接在
onCreate这类非挂起函数中调用await()或挂起函数,会触发编译错误,必须包裹在协程作用域(如lifecycleScope.launch,不推荐使用GlobalScope.launch避免内存泄漏)内。 - Retrofit 2.6及以上版本支持直接用
suspend函数定义接口方法,无需额外的CallAdapter,写法更简洁,推荐使用这种方式。 - 使用
lifecycleScope可以避免页面销毁后协程仍在执行导致的内存泄漏问题。
内容的提问来源于stack exchange,提问作者2WB
相关产品推荐
相关产品推荐

