在Android开发中,网络请求是必不可少的功能,而Retrofit和Kotlin协程的结合为网络请求提供了简洁高效的解决方案。本文通过实战演示,详细讲解如何封装Retrofit + 协程,实现统一的网络请求、错误处理和加载状态管理。从依赖配置、数据模型定义、API接口设计,到ViewModel中的数据管理和UI层的状态观察,一步步带你掌握现代Android开发中的网络请求最佳实践。无论是初学者还是经验丰富的开发者,都能从中受益,提升开发效率和代码质量。
以下是一个完整的 Retrofit + 协程 封装实战示例,包括网络请求的封装、错误处理、加载状态管理等。
1. 添加依赖
在 build.gradle 中添加必要的依赖:
dependencies {
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
// Kotlin Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4'
// Lifecycle (用于协程的 lifecycleScope)
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
}
2. 定义数据模型
data class User(
val id: Int,
val name: String,
val email: String
)
3. 定义 API 接口
使用 Retrofit 的注解定义 API 接口:
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: Int): User
@GET("users")
suspend fun getUsers(): List<User>
}
4. 封装 Retrofit 客户端
创建一个单例的 Retrofit 客户端:
object RetrofitClient {
private const val BASE_URL = "https://jsonplaceholder.typicode.com/"
private val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
val apiService: ApiService by lazy {
retrofit.create(ApiService::class.java)
}
}
5. 封装网络请求
封装一个通用的网络请求工具类,处理协程的异常和加载状态:
sealed class Result<out T> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Throwable) : Result<Nothing>()
object Loading : Result<Nothing>()
}
object NetworkHelper {
suspend fun <T> safeApiCall(apiCall: suspend () -> T): Result<T> {
return try {
Result.Success(apiCall())
} catch (e: Exception) {
Result.Error(e)
}
}
}
6. 在 ViewModel 中使用
在 ViewModel 中发起网络请求,并管理 UI 状态:
class UserViewModel : ViewModel() {
private val _userState = MutableLiveData<Result<User>>()
val userState: LiveData<Result<User>> get() = _userState
private val _usersState = MutableLiveData<Result<List<User>>>()
val usersState: LiveData<Result<List<User>>> get() = _usersState
fun fetchUser(userId: Int) {
viewModelScope.launch {
_userState.value = Result.Loading
_userState.value = NetworkHelper.safeApiCall {
RetrofitClient.apiService.getUser(userId)
}
}
}
fun fetchUsers() {
viewModelScope.launch {
_usersState.value = Result.Loading
_usersState.value = NetworkHelper.safeApiCall {
RetrofitClient.apiService.getUsers()
}
}
}
}
- 在 Activity/Fragment 中观察数据
在 UI 层观察 ViewModel 的数据,并更新 UI:
class UserActivity : AppCompatActivity() {
private val viewModel: UserViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_user)
// 观察用户数据
viewModel.userState.observe(this) { result ->
when (result) {
is Result.Loading -> showLoading()
is Result.Success -> showUser(result.data)
is Result.Error -> showError(result.exception.message)
}
}
// 观察用户列表数据
viewModel.usersState.observe(this) { result ->
when (result) {
is Result.Loading -> showLoading()
is Result.Success -> showUsers(result.data)
is Result.Error -> showError(result.exception.message)
}
}
// 发起请求
viewModel.fetchUser(1)
viewModel.fetchUsers()
}
private fun showLoading() {
// 显示加载动画
}
private fun showUser(user: User) {
// 更新 UI 显示用户信息
}
private fun showUsers(users: List<User>) {
// 更新 UI 显示用户列表
}
private fun showError(message: String?) {
// 显示错误信息
}
}
8. 错误处理
在 NetworkHelper 中已经捕获了异常,可以根据不同的异常类型(如网络异常、解析异常等)进行更细致的处理:
catch (e: IOException) {
Result.Error(Exception("网络连接失败,请检查网络设置"))
} catch (e: HttpException) {
Result.Error(Exception("服务器错误: ${e.code()}"))
} catch (e: Exception) {
Result.Error(Exception("未知错误: ${e.message}"))
}
9. 总结
通过以上封装,我们实现了以下功能:
Retrofit + 协程 的网络请求封装。
-
统一的错误处理和加载状态管理。
-
在 ViewModel 中管理数据,确保 UI 与数据分离。
-
在 UI 层观察数据变化,并更新 UI。
-
这种封装方式不仅提高了代码的可读性和可维护性,还能有效减少重复代码,适合中大型项目的开发。