目录
- 核心概念:网络请求与响应
- Android网络开发演进史
- 传统方式:
HttpURLConnection - 推荐方式:
OkHttp - 数据解析:
Gson/Moshi - 协程 + Retrofit:现代标准方案
- 传统方式:
- 现代网络请求最佳实践:Retrofit + OkHttp + Coroutines + Gson
- 为什么是这套组合?
- 完整实现步骤
- 代码示例
- 处理网络状态
- 检查网络连接
- 处理加载状态
- 优雅地处理错误
- 高级主题
- 数据缓存
- 文件上传与下载
- OAuth 2.0 认证
- WebSocket
- 安全与性能
- HTTPS
- 防止内存泄漏
- 网络超时与重试
- 学习资源推荐
核心概念:网络请求与响应
所有网络通信都遵循客户端-服务器模型:

- 客户端:你的Android App。
- 服务器:提供数据服务的远程计算机(如你的API服务器)。
一个典型的网络请求流程如下:
- 客户端发起请求:App创建一个请求,包含:
- URL:服务器的地址(
https://api.example.com/users)。 - HTTP方法:
GET(获取数据)、POST(提交数据)、PUT(更新数据)、DELETE(删除数据)等。 - 请求头:附加信息,如
Content-Type(数据类型)、Authorization(认证信息)。 - 请求体:对于
POST/PUT请求,要发送的数据(通常是JSON格式)。
- URL:服务器的地址(
- 服务器处理请求:服务器接收请求,执行相应的业务逻辑(如查询数据库)。
- 服务器返回响应:服务器将处理结果返回给客户端,包含:
- 响应码:如
200 OK(成功)、404 Not Found(资源不存在)、500 Internal Server Error(服务器错误)。 - 响应头:附加信息。
- 响应体:客户端需要的数据(通常是JSON格式)。
- 响应码:如
- 客户端处理响应:App解析响应体,更新UI或执行后续操作。
Android网络开发演进史
Android的网络库在不断进化,了解历史有助于理解为什么现在的方案是最佳选择。
传统方式:HttpURLConnection / HttpClient (已废弃)
- 优点:Android SDK内置,无需额外依赖。
- 缺点:
- API繁琐,使用不便。
- 不支持现代HTTP特性,如HTTP/2。
- 处理异步请求需要手动开线程和解析,容易出错。
HttpClient在API 22已被彻底废弃。
推荐方式:OkHttp
- 是什么:一个现代、高效、功能丰富的HTTP客户端。
- 优点:
- 自动管理连接池:复用TCP连接,极大提升性能。
- 支持HTTP/2:允许在单个连接上并行请求,速度快。
- 支持GZIP:自动压缩请求/响应体,减少流量。
- 强大的拦截器机制:可以统一处理日志、缓存、认证等。
- 简化了异步请求的处理。
数据解析:Gson / Moshi
- 是什么:JSON解析库,服务器返回的数据通常是JSON字符串,我们需要将其转换成Kotlin/Java对象(反序列化),或将对象转换成JSON字符串发送给服务器(序列化)。
- Gson:Google出品,稳定可靠,使用广泛。
- Moshi:Square出品(与Retrofit同一家),对Kotlin支持更好(默认支持
KClass),性能略优。
协程 + Retrofit:现代标准方案
- 是什么:
- Retrofit:一个类型安全的HTTP客户端,它不是直接发送网络请求,而是将Java/Kotlin接口注解(如
@GET,@POST)转换成OkHttp请求。 - Kotlin Coroutines:提供了一种更简洁、更安全的方式来处理异步代码,它避免了回调地狱,代码看起来像同步代码一样线性。
- Retrofit:一个类型安全的HTTP客户端,它不是直接发送网络请求,而是将Java/Kotlin接口注解(如
- 为什么是这套组合?
- 类型安全:Retrofit将API端点定义成接口,编译器会帮你检查URL、参数等是否正确。
- 代码简洁:配合协程,异步代码变得极其易读和易于维护。
- 功能强大:Retrofit内置了Gson/Moshi适配器、RxJava适配器等,生态系统非常完善。
- 社区标准:目前业界开发Android网络应用的首选和标准方案。
现代网络请求最佳实践:Retrofit + OkHttp + Coroutines + Gson
下面我们来实现一个从GitHub获取用户信息的完整例子。
第一步:添加依赖
在 app/build.gradle.kts (或 build.gradle) 文件中添加:

// OkHttp 和 Retrofit
implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0") // Gson转换器
implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") // OkHttp日志拦截器
// Coroutines
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
第二步:添加网络权限
在 app/src/main/AndroidManifest.xml 中:
<uses-permission android:name="android.permission.INTERNET" />
第三步:创建数据类
根据GitHub API返回的JSON结构创建Kotlin数据类。
import com.google.gson.annotations.SerializedName
data class User(
val login: String,
val id: Int,
val avatar_url: String,
val name: String?,
val bio: String?
)
// Response wrapper (if your API has one)
data class UserResponse(
val items: List<User>
)
第四步:创建Retrofit API接口
定义你的API方法。
import retrofit2.http.GET
import retrofit2.http.Path
interface GitHubApiService {
// GET https://api.github.com/users/{username}
@GET("users/{username}")
suspend fun getUser(@Path("username") username: String): User // 使用 suspend 关键字
// GET https://api.github.com/search/users?q=tetris
@GET("search/users")
suspend fun searchUsers(@Query("q") query: String): UserResponse // suspend 关键字
}
suspend关键字告诉协程这个函数是挂起函数,可以在协程中安全地调用。
第五步:创建Retrofit实例
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitClient {
private const val BASE_URL = "https://api.github.com/"
val instance: GitHubApiService by lazy {
// 创建日志拦截器
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
// 创建OkHttpClient并添加拦截器
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
// 创建Retrofit实例
Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(GitHubApiService::class.java)
}
}
第六步:在ViewModel或Activity/Fragment中调用
这是在 ViewModel 中使用协程进行网络请求的标准做法。
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class MyViewModel : ViewModel() {
// 使用 MutableLiveData 来持有UI状态
private val _user = MutableLiveData<User>()
val user: LiveData<User> = _user
private val _error = MutableLiveData<String>()
val error: LiveData<String> = _error
private val _isLoading = MutableLiveData<Boolean>()
val isLoading: LiveData<Boolean> = _isLoading
fun fetchUser(username: String) {
viewModelScope.launch { // 在协程作用域内启动
try {
_isLoading.value = true
val fetchedUser = RetrofitClient.instance.getUser(username)
_user.value = fetchedUser
} catch (e: Exception) {
_error.value = "Failed to fetch user: ${e.message}"
} finally {
_isLoading.value = false
}
}
}
}
第七步:在Activity/Fragment中观察LiveData并更新UI
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import coil.load // 使用 Coil 库加载图片
class MyActivity : AppCompatActivity() {
private lateinit var viewModel: MyViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my)
viewModel = ViewModelProvider(this).get(MyViewModel::class.java)
val button: Button = findViewById(R.id.button_fetch)
val progressBar: ProgressBar = findViewById(R.id.progress_bar)
val textViewName: TextView = findViewById(R.id.text_view_name)
val imageViewAvatar: ImageView = findViewById(R.id.image_view_avatar)
viewModel.isLoading.observe(this) { isLoading ->
progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
}
viewModel.user.observe(this) { user ->
textViewName.text = user.name ?: user.login
imageViewAvatar.load(user.avatar_url) {
crossfade(true)
placeholder(R.drawable.ic_placeholder) // 占位图
error(R.drawable.ic_error) // 错误图
}
}
viewModel.error.observe(this) { errorMessage ->
Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT).show()
}
button.setOnClickListener {
viewModel.fetchUser("google") // 获取 "google" 用户的资料
}
}
}
处理网络状态
检查网络连接
可以使用 ConnectivityManager 来检查网络是否可用。
fun isNetworkAvailable(context: Context): Boolean {
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val activeNetwork = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
} else {
@Suppress("DEPRECATION")
val networkInfo = connectivityManager.activeNetworkInfo ?: return false
@Suppress("DEPRECATION")
return networkInfo.isConnected
}
}
在发起网络请求前,最好先检查一下,并提示用户。
处理加载状态
如上面的例子所示,使用一个 isLoading 的 LiveData 来控制进度条或加载动画的显示/隐藏。
优雅地处理错误
使用 try-catch 块捕获网络请求可能抛出的异常(如 IOException, HttpException),并通过一个 error 的 LiveData 将错误信息传递给UI层,显示给用户。
高级主题
- 数据缓存:OkHttp内置了强大的缓存机制,只需在构建
OkHttpClient时配置一个Cache目录即可,你也可以使用Retrofit的@CacheControl注解来控制缓存策略。 - 文件上传与下载:
- 下载:Retrofit的
@Streaming注解可以处理大文件下载,防止内存溢出。 - 上传:使用
@Multipart和@Part注解,并传递RequestBody或MultipartBody.Part。
- 下载:Retrofit的
- OAuth 2.0 认证:对于需要用户登录的API,通常使用OAuth 2.0,可以使用
Interceptor在每个请求中添加Authorization头。 - WebSocket:OkHttp也提供了对WebSocket的支持,适合需要实时、双向通信的场景,如聊天室、实时通知等。
安全与性能
- HTTPS:必须使用HTTPS! 它可以加密数据,防止中间人攻击,Retrofit和OkHttp默认支持HTTPS。
- 防止内存泄漏:在
ViewModel中使用viewModelScope.launch可以确保当ViewModel被销毁时,所有正在运行的协程都会自动取消,从而避免内存泄漏。 - 网络超时与重试:可以在
OkHttpClient中配置connectTimeout,readTimeout,writeTimeout,使用Interceptor可以实现自动重试逻辑。
学习资源推荐
- 官方文档:
- 优秀教程:
- ProAndroidDev:Medium上的一个高质量博客,有很多关于Android架构和现代开发的深入文章。
- Android Developer Fundamentals (Kotlin):Google官方的免费课程,其中网络部分讲得很好。
- B站/YouTube:搜索 "Android Retrofit", "Kotlin Coroutines" 等关键词,有很多视频教程。
- 代码示例:
- Android Jetpack Samples:Google官方的架构示例项目,包含了网络请求的最佳实践。
希望这份详细的指南能帮助你顺利入门并精通Android网络应用开发!
