跳转至

10 网络请求基础

App 联网(拉取数据、提交表单)是最常见需求之一。安卓不允许在主线程做网络请求(会崩/卡死),所以必须放子线程。

10.1 添加网络权限

AndroidManifest.xml 里 <manifest> 下加:

<uses-permission android:name="android.permission.INTERNET" />

注意:调试 http(非 https)明文地址,Android 9+ 默认禁止明文流量。开发期可在 AndroidManifest.xml 的 <application> 加 android:usesCleartextTraffic="true";正式环境应全用 https。

10.2 依赖与选库

库 说明
HttpURLConnection JDK 自带,零依赖,学原理用
OkHttp 最流行的网络库,好用
Retrofit 在 OkHttp 之上做接口封装,大项目标配
Gson / Moshi JSON 解析

推荐起步 OkHttp + Gson:

implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.google.code.gson:gson:2.10.1")

10.3 OkHttp GET 示例

OkHttpClient client = new OkHttpClient();

// 请求必须放子线程
new Thread(() -> {
    try {
        Request request = new Request.Builder()
                .url("https://api.example.com/articles")
                .build();
        try (Response response = client.newCall(request).execute()) {
            String body = response.body().string();   // JSON 字符串
            // 回到主线程更新 UI
            runOnUiThread(() -> {
                tvResult.setText(body);
            });
        }
    } catch (Exception e) {
        runOnUiThread(() -> Toast.makeText(this, "请求失败:" + e.getMessage(), Toast.LENGTH_SHORT).show());
    }
}).start();

10.4 POST + JSON 示例

new Thread(() -> {
    try {
        String json = "{\"username\":\"pyz\",\"password\":\"123456\"}";
        RequestBody body = RequestBody.create(
                json, okhttp3.MediaType.parse("application/json; charset=utf-8"));
        Request request = new Request.Builder()
                .url("https://api.example.com/login")
                .post(body)
                .build();
        try (Response response = client.newCall(request).execute()) {
            String resp = response.body().string();
            runOnUiThread(() -> tvResult.setText(resp));
        }
    } catch (Exception e) {
        runOnUiThread(() -> Toast.makeText(this, "请求失败", Toast.LENGTH_SHORT).show());
    }
}).start();

10.5 Gson 解析 JSON

// JSON: [{"id":1,"title":"标题A"},{"id":2,"title":"标题B"}]
// 对应类:
// public class Item { public int id; public String title; }

Type type = new TypeToken<List<Item>>(){}.getType();
List<Item> items = new Gson().fromJson(jsonStr, type);
// items 就能直接塞进 RecyclerView 了

10.6 子线程三件套

需求 写法
开线程 new Thread(() -> {...}).start()
回主线程更新 UI runOnUiThread(() -> {...})
Activity 销毁了别乱更新 更新前判断 if (isFinishing() || isDestroyed()) return;

进阶提示:更规范的做法是 Handler/Looper、协程或 RxJava,但"Thread + runOnUiThread"足够理解全部原理。

10.7 常见报错排查

报错/现象 原因
NetworkOnMainThreadException 网络请求写主线程了,挪进子线程
CLEARTEXT communication not permitted 用了 http 明文,正式环境换 https,或加 usesCleartextTraffic
请求超时 网络不通/地址错/服务器没开;先在浏览器验证 URL
返回 JSON 解析报错 用在线 JSON 查看器核对字段名是否一致

本章练习:找一个公开 API(如天气/GitHub),GET 回来用 Gson 解析成对象并 Toast/显示第一条数据。

🏠 返回总站