- 服务器端: 创建一个 API,它能接收 HTTP 请求,并返回 JSON 格式的数据。
- Android 客户端: 在 Android 应用中发起网络请求,接收服务器返回的 JSON 数据,并将其解析成 Android 可以使用的对象。
第一部分:服务器端 - 如何设计一个 JSON API
服务器端技术栈有很多选择,Node.js (Express), Java (Spring Boot), Python (Django/Flask), PHP (Laravel) 等,无论使用哪种技术,核心原则是相似的。

API 设计
一个典型的 API 端点看起来像这样:https://api.example.com/v1/users
-
HTTP 方法:
GET: 从服务器获取数据(最常用)。POST: 向服务器发送数据以创建新资源。PUT/PATCH: 更新服务器上的现有资源。DELETE: 删除服务器上的资源。
-
响应格式: 服务器返回的数据必须是纯文本的 JSON 格式。
示例:使用 Node.js (Express) 创建一个简单的 API
这是一个非常流行的轻量级服务器框架。

安装 Express:
npm init -y npm install express
创建 server.js 文件:
const express = require('express');
const app = express();
const PORT = 3000;
// 中间件,用于解析 JSON 请求体
app.use(express.json());
// 模拟一个数据库
let users = [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Bob', email: 'bob@example.com' }
];
// 1. GET 请求:获取所有用户列表
app.get('/api/users', (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.status(200).json(users);
});
// 2. GET 请求:根据 ID 获取单个用户
app.get('/api/users/:id', (req, res) => {
const userId = parseInt(req.params.id);
const user = users.find(u => u.id === userId);
if (user) {
res.setHeader('Content-Type', 'application/json');
res.status(200).json(user);
} else {
res.status(404).json({ message: 'User not found' });
}
});
// 3. POST 请求:创建一个新用户
app.post('/api/users', (req, res) => {
const newUser = {
id: users.length + 1,
name: req.body.name,
email: req.body.email
};
users.push(newUser);
res.setHeader('Content-Type', 'application/json');
res.status(201).json(newUser);
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
运行服务器:
node server.js
你可以使用 Postman 或浏览器访问 http://localhost:3000/api/users 来获取 JSON 数据。
第二部分:Android 客户端 - 如何与 JSON API 交互
在 Android 中,处理网络请求和 JSON 解析有几种方式,从最基础的到现代推荐的。
使用 HttpURLConnection (传统方式)
这是 Android SDK 自带的,不需要额外依赖,但代码量较多,需要手动处理线程和解析。
步骤:
-
添加网络权限 (
AndroidManifest.xml):<uses-permission android:name="android.permission.INTERNET" />
在
<application>标签中添加android:usesCleartextTraffic="true"(如果你的 API 是http而不是https)。 -
创建数据模型类: 这个类必须与服务器返回的 JSON 结构完全对应,推荐使用 Kotlinx Serialization 或 Moshi 等库,但这里为了简单,我们手动创建。
// User.kt data class User( val id: Int, val name: String, val email: String ) -
创建网络请求工具类: 注意:网络操作不能在主线程执行,否则会抛出
NetworkOnMainThreadException,我们使用Thread或Coroutine。import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import java.io.BufferedReader import java.io.InputStreamReader import java.net.HttpURLConnection import java.net.URL class MainActivity : AppCompatActivity() { private val TAG = "MainActivity" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 在后台线程发起请求 Thread { fetchUsers() }.start() } private fun fetchUsers() { val apiUrl = "http://10.0.2.2:3000/api/users" // Android 模拟器访问本地电脑的地址是 10.0.2.2 try { val url = URL(apiUrl) val urlConnection = url.openConnection() as HttpURLConnection urlConnection.requestMethod = "GET" urlConnection.connectTimeout = 15000 urlConnection.readTimeout = 15000 if (urlConnection.responseCode == HttpURLConnection.HTTP_OK) { val inputStream = urlConnection.inputStream val reader = BufferedReader(InputStreamReader(inputStream)) val response = StringBuilder() var line: String? while (reader.readLine().also { line = it } != null) { response.append(line) } reader.close() inputStream.close() // 解析 JSON 并在主线程更新 UI // 注意:这里为了简化,省略了 JSON 解析部分,后面会讲 Log.d(TAG, "Response: $response") } else { Log.e(TAG, "Error: ${urlConnection.responseCode}") } } catch (e: Exception) { Log.e(TAG, "Exception: ${e.message}") } } }
HttpURLConnection 的缺点很明显:代码冗长,解析 JSON 非常繁琐。
使用现代网络库 (强烈推荐)
现代库极大地简化了网络请求和 JSON 解析。
添加依赖
在你的 build.gradle (Module: app) 文件中添加 Retrofit 和 Moshi 的依赖。
// build.gradle (Module: app) // Retrofit for networking implementation 'com.squareup.retrofit2:retrofit:2.9.0' // Moshi for JSON parsing implementation 'com.squareup.moshi:moshi:1.14.0' implementation 'com.squareup.moshi:moshi-kotlin:1.14.0' // For Kotlin support // Kotlin Coroutines for asynchronous programming implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4' // Retrofit adapter for Coroutines implementation 'com.squareup.retrofit2:adapter-coroutines:0.9.2'
设置 Retrofit
创建一个 Retrofit 实例,告诉它你的 API 基础 URL 和如何解析 JSON (使用 Moshi)。
// ApiClient.kt
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
object ApiClient {
private const val BASE_URL = "http://10.0.2.2:3000/"
val instance: Retrofit by lazy {
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(MoshiConverterFactory.create())
.build()
}
}
定义 API 接口
创建一个 Kotlin 接口,用注解来描述你的 API 端点,Retrofit 会实现这个接口。
// ApiService.kt
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
interface ApiService {
@GET("api/users")
suspend fun getUsers(): List<User> // 使用 suspend 函数,可以在协程中直接调用
@GET("api/users/{id}")
suspend fun getUserById(@Path("id") id: Int): User
@POST("api/users")
suspend fun createUser(@Body user: User): User // @Body 表示请求体是 User 对象
}
在 Activity/ViewModel 中使用
你可以像调用普通函数一样发起网络请求,代码非常简洁。
// MainActivity.kt
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch
import retrofit2.HttpException
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 获取 ApiService 实例
val apiService = ApiClient.instance.create(ApiService::class.java)
// 在协程作用域内发起网络请求
lifecycleScope.launch {
try {
// 调用 API
val users = apiService.getUsers()
// 在主线程更新 UI
users.forEach { user ->
Log.d(TAG, "Fetched User: ${user.name}, Email: ${user.email}")
}
} catch (e: HttpException) {
// 处理 HTTP 错误 (404, 500)
Log.e(TAG, "HTTP Error: ${e.code()} - ${e.message()}")
} catch (e: Exception) {
// 处理其他错误 (例如网络连接问题)
Log.e(TAG, "Network Error: ${e.message}")
}
}
}
}
总结与最佳实践
| 特性 | HttpURLConnection |
Retrofit + Moshi |
|---|---|---|
| 易用性 | 低,代码繁琐 | 高,接口定义清晰 |
| 功能 | 基础功能 | 强大,支持同步/异步、拦截器、适配器等 |
| JSON 解析 | 需手动或使用其他库 (如 Gson) | 集成 Moshi/Gson,自动转换 |
| 线程管理 | 需手动处理 (AsyncTask, Thread, Handler) | 通过 Call 或 suspend 函数自动处理 |
| 推荐度 | 仅用于简单项目或不想引入第三方库时 | 强烈推荐,是现代 Android 开发的标准 |
最佳实践建议:
-
使用现代库: 直接选择 Retrofit + Moshi/Gson + Kotlin Coroutines 的组合,这是目前 Android 官方和社区最推崇的方案。
-
将网络逻辑与 UI 分离: 在
ViewModel中进行网络请求,而不是在Activity或Fragment中。ViewModel可以帮助配置更改(如屏幕旋转)时保持数据。 -
使用协程:
suspend函数让异步代码看起来像同步代码,大大提高了可读性。 -
处理错误: 始终捕获
HttpException来处理服务器返回的错误状态码(如 404, 500),并捕获IOException来处理网络连接问题。 -
添加数据转换器: 使用 Moshi 或 Gson 的
@Json注解,可以灵活处理 JSON 和 Kotlin 数据模型之间的字段名不匹配等问题。// User.kt import com.squareup.moshi.Json data class User( @Json(name = "id") val userId: Int, // JSON 中的 "id" 映射到 Kotlin 的 "userId" @Json(name = "name") val userName: String, // JSON 中的 "name" 映射到 "userName" val email: String )
