上一篇
安卓从服务器获取json数据
- 行业动态
- 2025-04-24
- 1
安卓应用配置网络权限,通过OkHttp/Retrofit异步请求服务器JSON数据,Gson解析为对象并处理异常,验证数据后于主线程更新UI
前置准备
添加网络权限
在 AndroidManifest.xml
中声明网络访问权限:
<uses-permission android:name="android.permission.INTERNET" />
选择网络库
- 原生 API:
HttpURLConnection
(轻量但代码较多) - 第三方库:
OkHttp
(简洁高效)、Retrofit
(适合复杂 API 调用) - JSON 解析库:
org.json
(内置)、Gson
(Google 出品)、Moshi
(现代化)
实现步骤(以 OkHttp + Gson 为例)
添加依赖
在 build.gradle
中添加:
implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.google.code.gson:gson:2.10.1'
创建数据模型类
假设 JSON 数据格式为:
{ "name": "张三", "age": 25, "hobbies": ["篮球", "阅读"] }
对应 Java 类:
public class User { private String name; private int age; private List<String> hobbies; // Getter 和 Setter 方法 }
发起网络请求
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import com.google.gson.Gson; import java.io.IOException; public class JsonFetcher { private static final String URL = "https://example.com/api/user"; public void fetchData() { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url(URL) .build(); client.newCall(request).enqueue(new okhttp3.Callback() { @Override public void onFailure(Call call, IOException e) { // 处理失败(如网络错误) runOnMainThread(() -> { // 更新 UI 或日志 Log.e("NetworkError", e.getMessage()); }); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful()) { String jsonData = response.body().string(); parseJson(jsonData); } else { // 处理 HTTP 错误(如 404) runOnMainThread(() -> { Log.e("HTTPError", "Code: " + response.code()); }); } } }); } private void parseJson(String json) { Gson gson = new Gson(); User user = gson.fromJson(json, User.class); runOnMainThread(() -> { // 更新 UI(如设置 TextView) textView.setText(user.getName() + ", 年龄:" + user.getAge()); }); } private void runOnMainThread(Runnable task) { new Handler(Looper.getMainLooper()).post(task); } }
关键问题处理
问题 | 解决方案 |
---|---|
主线程网络请求崩溃 | 使用子线程(如 AsyncTask 、Thread )或异步框架(如 RxJava、协程) |
JSON 解析失败 | 检查字段名是否匹配,使用 @SerializedName 注解处理命名不一致问题 |
SSL 证书验证失败 | 在 OkHttp 中配置 sslSocketFactory ,或调试时临时禁用验证(不推荐生产环境) |
乱码问题 | 确保服务器返回 UTF-8 编码,客户端也按 UTF-8 解析 |
常见问题与解答
问题 1:如何发送带参数的 POST 请求?
解答:
修改 Request.Builder
并添加请求体:
MediaType JSON = MediaType.get("application/json; charset=utf-8"); String postBody = new Gson().toJson(new User("李四", 30, null)); // 构造 JSON Request request = new Request.Builder() .url("https://example.com/api/user") .post(RequestBody.create(postBody, JSON)) .build();
问题 2:如何解析嵌套 JSON 对象?
解答:
定义嵌套类或使用 @SerializedName
:
public class User { private String name; @SerializedName("profile") // 对应 JSON 中的 profile 对象 private Profile profile; // 其他字段和 Getter/Setter } public class Profile { private String city; private String phone; // Getter/Setter }
扩展优化建议
优化方向 | 说明 |
---|---|
缓存数据 | 使用 OkHttp 的缓存机制或集成 Room 数据库存储数据 |
错误重试机制 | 通过拦截器(Interceptor)实现自动重试 |
安全性 | 使用 HTTPS,配置证书锁定(Certificate Pinning) |
性能优化 | 使用 Kotlin 协程替代回调,简化异步逻辑 |