Retrofit + Kotlin 协程(Android 实战教程)
Retrofit Kotlin 协程Android 实战教程这是 Android 开发里最主流的网络请求方案Retrofit Coroutines MVVM现代 Android 项目基本都这么写。这一篇会从Retrofit 基础suspend 网络请求协程切线程MVVM 实战错误处理Flow 配合封装最佳实践一路讲到项目级写法。一、Retrofit 是什么Retrofit 是 Square 出的网络请求库。作用把 HTTP API 变成 Kotlin 接口以前Retrofit 之后HttpURLConnection / OkHttpapi.getUser()非常麻烦直接像调用本地函数二、Retrofit 为什么和协程绝配以前 RetrofitCall.enqueue()回调地狱api.getUser().enqueue(...)协程之后valuserapi.getUser()像同步代码。但底层仍然是异步。这就是suspend Retrofit的威力。三、添加依赖// Retrofitimplementationcom.squareup.retrofit2:retrofit:2.11.0implementationcom.squareup.retrofit2:converter-gson:2.11.0// 协程implementationorg.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1// ViewModelimplementationandroidx.lifecycle:lifecycle-viewmodel-ktx:2.8.0implementationandroidx.lifecycle:lifecycle-runtime-ktx:2.8.0四、Retrofit 基础配置五、创建 Data 类dataclassUser(valid:Int,valname:String)六、创建 API 接口这是 Retrofit 核心。interfaceApiService{GET(user)suspendfungetUser():User}重点suspendRetrofit 会自动支持协程。七、创建 RetrofitobjectRetrofitManager{valapi:ApiServicebylazy{Retrofit.Builder().baseUrl(https://example.com/).addConverterFactory(GsonConverterFactory.create()).build().create(ApiService::class.java)}}八、第一个协程网络请求ViewModelclassUserViewModel:ViewModel(){funloadUser(){viewModelScope.launch{valuserRetrofitManager.api.getUser()println(user.name)}}}九、为什么 suspend 不需要 enqueue以前现在enqueue(callback)suspend funRetrofit 内部已经帮你做了异步线程Continuation.resume()这就是协程适配器。十、Retrofit Continuation 原理你写suspendfungetUser():UserRetrofit 底层其实拿到了ContinuationUser网络返回后continuation.resume(user)协程恢复。十一、为什么不会阻塞主线程很多人疑惑viewModelScope.launch{api.getUser()// 不是在 Main 线程吗}为什么不卡 UI因为Retrofit 内部自动切到 OkHttp 线程池网络完成后再恢复协程。所以你看起来像同步实际上是异步。十二、withContext 什么时候需要Retrofit 请求本身不需要withContext(IO)因为 Retrofit 已经异步。但 JSON 大解析需要valresultwithContext(Dispatchers.Default){parseBigJson()}数据库操作withContext(Dispatchers.IO)十三、POST 请求APIinterfaceApiService{POST(login)suspendfunlogin(Bodybody:LoginRequest):LoginResponse}RequestdataclassLoginRequest(valusername:String,valpassword:String)十四、Query 参数GET(user)suspendfungetUser(Query(id)id:Int):User// 请求/user?id1十五、Path 参数GET(user/{id})suspendfungetUser(Path(id)id:Int):User// 请求/user/1十六、错误处理非常重要很多人项目里直接崩。正确写法viewModelScope.launch{try{valuserapi.getUser()}catch(e:Exception){e.printStackTrace()}}十七、为什么会抛异常Retrofit 协程网络失败会直接throw Exception而不是onFailure()。十八、项目级错误封装推荐ResultStatesealedclassResultStateoutT{dataclassSuccessT(valdata:T):ResultStateT()dataclassError(valmsg:String):ResultStateNothing()objectLoading:ResultStateNothing()}十九、统一请求封装suspendfunTsafeApiCall(apiCall:suspend()-T):ResultStateT{returntry{ResultState.Success(apiCall())}catch(e:Exception){ResultState.Error(e.message?:未知错误)}}二十、使用方式viewModelScope.launch{when(valresultsafeApiCall{api.getUser()}){isResultState.Success-{// 处理成功}isResultState.Error-{// 处理错误}else-{}}}二十一、Repository 层MVVM核心现代 Android必须分层。二十二、RepositoryclassUserRepository{suspendfungetUser():User{returnRetrofitManager.api.getUser()}}二十三、ViewModelclassUserViewModel:ViewModel(){privatevalrepositoryUserRepository()funload(){viewModelScope.launch{valuserrepository.getUser()}}}二十四、为什么需要 Repository因为 ViewModel 不应该直接操作 Retrofit否则耦合严重不好测试难维护二十五、Flow Retrofit现代方案这是现在最推荐的。RepositoryclassUserRepository{fungetUser()flow{emit(ResultState.Loading)try{valuserapi.getUser()emit(ResultState.Success(user))}catch(e:Exception){emit(ResultState.Error(请求失败))}}}ViewModelfunloadUser(){viewModelScope.launch{repository.getUser().collect{// 处理状态}}}二十六、Flow 的优势比 suspend 更适合UI状态Loading连续数据重试分页二十七、Retrofit OkHttpRetrofit 底层其实是OkHttp。二十八、添加日志拦截器依赖implementationcom.squareup.okhttp3:logging-interceptor:4.12.0配置valloggingHttpLoggingInterceptor()logging.levelHttpLoggingInterceptor.Level.BODY二十九、OkHttpClientvalclientOkHttpClient.Builder().addInterceptor(logging).build()三十、Retrofit 使用 clientRetrofit.Builder().client(client)三十一、拦截器项目必会Token 拦截器classTokenInterceptor:Interceptor{overridefunintercept(chain:Interceptor.Chain):Response{valrequestchain.request().newBuilder().addHeader(token,xxx).build()returnchain.proceed(request)}}三十二、超时设置OkHttpClient.Builder().connectTimeout(10,TimeUnit.SECONDS).readTimeout(10,TimeUnit.SECONDS)三十三、协程取消与 Retrofit这是高频面试题。当协程 cancel 时Retrofit 会自动取消网络请求。因为Retrofit 协程和 Job 已关联。三十四、真正的项目结构推荐ui/ viewmodel/ repository/ network/ model/三十五、标准企业级结构层级职责ApiService定义网络接口RetrofitManagerRetrofit 配置管理Repository数据仓储隔离网络层ViewModel业务逻辑UI状态管理UIActivity / Fragment / Compose三十六、Compose Retrofit在 Jetpack Compose 中LaunchedEffect(Unit){viewModel.load()}ViewModelviewModelScope.launch这是现代 Android 官方方案。三十七、Retrofit 常见面试题1. suspend 为什么不阻塞因为Retrofit 底层OkHttp异步Continuation恢复2. Retrofit 为什么不需要 withContext(IO)因为Retrofit 已经异步3. Retrofit 底层是谁Retrofit ↓ OkHttp4. 协程取消为什么能取消请求因为Coroutine Job关联OkHttp Call.cancel()5. suspend 本质是什么编译器Continuation 状态机三十八、现代 Android 最推荐写法ViewModelclassUserViewModel:ViewModel(){valuiStateMutableStateFlowResultStateUser(ResultState.Loading)funloadUser(){viewModelScope.launch{uiState.valueResultState.Loading uiState.valuetry{ResultState.Success(api.getUser())}catch(e:Exception){ResultState.Error(失败)}}}}三十九、真正的大脑模型以后看到suspend fun getUser()你脑子里应该自动出现Retrofit ↓ OkHttp异步请求 ↓ Continuation挂起 ↓ 网络返回 ↓ resume恢复协程 ↓ 继续执行四十、总结组件作用RetrofitHTTP → Kotlin 接口suspend协程挂起 异步OkHttp底层网络执行Repository隔离网络层ViewModel状态管理与业务逻辑StateFlow / FlowUI状态响应ResultState统一错误处理四十一、企业级最佳实践非常重要不要这样Activity-Retrofit要这样UI ↓ ViewModel ↓ Repository ↓ Retrofit最后一句真正理解 Retrofit 协程Retrofit 协程真正厉害的地方不是“代码变短”。而是把异步回调变成了同步思维底层Continuation 状态机 OkHttp异步上层像写同步代码一样写异步这就是现代 Android 网络架构的核心。