目录
-
核心概念
(图片来源网络,侵删)- 客户端 (Android App)
- 服务器端
- 通信协议 (HTTP/HTTPS)
- 数据格式 (JSON, XML, Form Data)
- 认证与授权
-
上传数据的类型
- 文本数据 (JSON, XML, Form)
- 文件上传 (图片, 视频, 文档)
- 混合数据 (文本 + 文件)
-
Android 端实现方案
HttpURLConnection(原生, Java/Kotlin)- 优点:无需第三方库,Android SDK 自带。
- 缺点:代码相对繁琐,处理复杂逻辑(如文件上传)较麻烦。
OkHttp(强烈推荐)优点:现代、高效、易用,支持同步/异步请求,内置拦截器,是当前 Android 开发的主流选择。
Retrofit(基于 OkHttp)优点:将网络请求接口化,通过注解配置,代码结构清晰,易于维护和测试,非常适合大型项目。
(图片来源网络,侵删)
-
详细代码示例 (以 Retrofit + OkHttp 为例)
-
关键注意事项与最佳实践
- 网络权限
- 在后台执行网络请求 (WorkManager)
- 错误处理
- 安全性 (HTTPS)
- 数据压缩
- 日志 (Logging Interceptor)
核心概念
- 客户端 (Android App): 你的应用,负责收集数据并发起网络请求。
- 服务器端: 运行在远程服务器上的程序(如用 Java Spring Boot, Node.js, Python Django 等编写),负责接收、处理、存储数据并返回响应。
- 通信协议: 客户端和服务器之间“对话”的语言,最常用的是 HTTP/HTTPS,HTTPS 是 HTTP 的安全版本,对数据进行加密,是现在的标准。
- 数据格式: 上传的数据需要被服务器理解,常见格式有:
- JSON (JavaScript Object Notation): 轻量级,易于人阅读和编写,也易于机器解析和生成。是目前最主流的选择。
- XML (eXtensible Markup Language): 结构化,但比 JSON 冗余。
- Form Data: 传统的表单提交格式,适用于简单的键值对,也常用于文件上传。
- 认证与授权: 服务器需要知道是谁在请求,以及是否有权限进行操作,常见方式有:
- Token (如 JWT): 客户端在登录后获得一个令牌,后续请求在 Header 中携带此令牌。
- API Key: 在请求 Header 或参数中提供一个密钥。
- OAuth: 用于授权第三方应用访问用户数据。
上传数据的类型
a. 文本数据 (如 JSON)
这是最常见的场景,比如上传用户信息、订单数据等。
示例 JSON:

{
"username": "john_doe",
"email": "john.doe@example.com",
"age": 30
}
b. 文件上传 (如图片)
通常使用 multipart/form-data 格式,它会将文件分割成多个部分,与文本数据一起上传。
c. 混合数据 (如用户头像 + 用户信息)
同时包含文本和文件,也使用 multipart/form-data 格式。
Android 端实现方案
HttpURLConnection (原生)
这是最基础的方式,不依赖任何库,适合学习网络原理,但不推荐用于生产项目。
OkHttp
OkHttp 是一个强大的 HTTP 客户端,它处理了连接池、重试、缓存等复杂问题,让开发者可以专注于业务逻辑。
特点:
- 支持 HTTP/2,允许同一主机上的所有请求共享一个 socket。
- 内置拦截器,可以轻松实现日志、缓存、认证等功能。
- 异步请求不会阻塞主线程。
Retrofit (推荐)
Retrofit 是 Square 公司(也是 OkHttp 的开发者)出品的一个类型安全的 HTTP 客户端,它将网络请求抽象成一个 Java/Kotlin 接口。
工作原理:
- 你定义一个接口,用注解描述 API 的 URL、请求方法、参数、返回类型等。
- Retrofit 根据这个接口生成一个动态代理对象。
- 你调用代理对象的方法,Retrofit 会自动将调用转换为 OkHttp 请求,并解析服务器返回的数据。
优点:
- 代码清晰: 网络请求逻辑与业务逻辑分离。
- 类型安全: 编译时就能检查接口定义是否正确。
- 易于扩展: 方便集成 Gson、Moshi、Jackson 等库进行序列化和反序列化。
详细代码示例 (Retrofit + OkHttp + Multipart)
这是目前最流行、最健壮的方案,我们将以上传用户头像(图片)和用户名(文本)为例。
步骤 1: 添加依赖 (build.gradle.kts 或 build.gradle)
// build.gradle (Module: app)
dependencies {
// 1. Retrofit: 用于定义和执行 API 请求
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
// 2. Gson: 用于 JSON 序列化和反序列化
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
// 3. OkHttp: Retrofit 的底层依赖,我们添加日志拦截器
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
// 4. Multipart/FormData: 用于文件上传
// Retrofit 2.6+ 已内置支持,无需额外依赖
// 5. 图片加载库 (可选,但强烈推荐)
implementation 'com.github.bumptech.glide:glide:4.12.0'
}
步骤 2: 添加网络权限 (app/src/main/AndroidManifest.xml)
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
...
</application>
</manifest>
步骤 3: 创建数据模型 (用于请求和响应)
// 用于接收服务器响应的模型
data class UploadResponse(
val success: Boolean,
val message: String,
val user: User? // 假设服务器返回了更新后的用户信息
)
data class User(
val id: String,
val username: String,
val avatarUrl: String
)
步骤 4: 定义 API 接口
使用 Retrofit 的注解来描述 API。
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
interface ApiService {
// @Multipart 表示这是一个 multipart/form-data 请求
// @POST 指定请求的 URL 路径
// @Part 用于指定请求中的一个部分
@Multipart
@POST("api/user/update_profile")
fun updateUserProfile(
@Part("username") username: RequestBody, // 文本部分
@Part("avatar") avatar: MultipartBody.Part // 文件部分
): Call<UploadResponse> // Call 对象代表一个待执行的请求
}
@Part("username"):"username"是表单中的字段名。RequestBody用于包装文本数据。@Part("avatar"):"avatar"是表单中的字段名。MultipartBody.Part是专门用于文件上传的。
步骤 5: 创建 Retrofit 实例并进行配置
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
object RetrofitClient {
private const val BASE_URL = "https://your-api-server.com/" // 替换为你的服务器地址
val instance: ApiService by lazy {
// 1. 创建 OkHttp 客户端
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY // 打印详细的日志
})
.connectTimeout(30, TimeUnit.SECONDS) // 连接超时
.readTimeout(30, TimeUnit.SECONDS) // 读取超时
.writeTimeout(30, TimeUnit.SECONDS) // 写入超时
.build()
// 2. 创建 Retrofit 实例
val retrofit = Retrofit 