1. 使用HttpURLConnection发起GET请求并解析响应

HttpURLConnection GET 请求的核心链路

在 Android 中发起一次 GET 请求,本质上是把「权限声明 → 后台线程 → 建立连接 → 读取响应 → 更新 UI」串成一条完整链路。HttpURLConnection 本身是同步阻塞 API,因此必须放在工作线程中执行,否则会触发 NetworkOnMainThreadException。

HttpURLConnection GET 请求执行链路 AndroidManifest INTERNET 权限声明 主线程 (UI Thread) 禁止网络操作 工作线程 new Thread / Executor 检查权限 切换线程 HttpURLConnection 1. openConnection() 2. setRequestMethod("GET") 3. connect() / getInputStream() 4. getResponseCode() 5. 读取 InputStream 发起请求 响应码判断 200 → 读取响应体 4xx/5xx → 异常处理 响应体解析 BufferedReader 逐行读取 StringBuilder 拼接 回传 UI 线程 runOnUiThread / Handler getResponseCode() 200 结果 异常分支 IOException / 超时 / 无网络

关键实现代码

下面是一个完整可运行的 GET 请求方法,包含权限检查、线程切换、响应码判断和响应体读取:

// AndroidManifest.xml 中声明
// <uses-permission android:name="android.permission.INTERNET" />

public class HttpGetTask {

    private static final String TAG = "HttpGetTask";

    /**
     * 在后台线程发起 GET 请求,通过回调返回结果
     */
    public static void doGet(final String urlStr, final Callback callback) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection conn = null;
                try {
                    URL url = new URL(urlStr);
                    conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);

                    int responseCode = conn.getResponseCode();
                    Log.d(TAG, "响应码: " + responseCode);

                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        // 读取响应体
                        InputStream is = conn.getInputStream();
                        BufferedReader reader = new BufferedReader(
                                new InputStreamReader(is, "UTF-8"));
                        StringBuilder sb = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            sb.append(line).append("\n");
                        }
                        reader.close();
                        is.close();

                        final String body = sb.toString().trim();
                        callback.onSuccess(responseCode, body);
                    } else {
                        callback.onError(responseCode, "HTTP " + responseCode);
                    }

                } catch (IOException e) {
                    Log.e(TAG, "请求失败", e);
                    callback.onError(-1, e.getMessage());
                } finally {
                    if (conn != null) {
                        conn.disconnect();
                    }
                }
            }
        }).start();
    }

    public interface Callback {
        void onSuccess(int code, String body);
        void onError(int code, String message);
    }
}

在 Activity 中调用并更新 UI

public class MainActivity extends AppCompatActivity {

    private TextView tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvResult = findViewById(R.id.tv_result);

        HttpGetTask.doGet("https://httpbin.org/get", new HttpGetTask.Callback() {
            @Override
            public void onSuccess(final int code, final String body) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tvResult.setText("响应码: " + code + "\n\n" + body);
                    }
                });
            }

            @Override
            public void onError(final int code, final String message) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tvResult.setText("请求失败: " + message);
                    }
                });
            }
        });
    }
}
验证要点:运行后观察 Logcat 中打印的响应码是否为 200;TextView 是否显示 httpbin.org 返回的 JSON 内容。若出现 NetworkOnMainThreadException,说明请求仍在主线程执行;若出现 SecurityException,说明未声明 INTERNET 权限。
常见坑:Android 9.0(API 28)及以上默认禁止明文 HTTP 请求。如果测试地址是 http:// 开头,需要在 AndroidManifest.xml 的 <application> 标签中添加 android:usesCleartextTraffic="true",或改用 HTTPS 地址。

响应码与处理策略对照

响应码 含义 处理方式
200 请求成功 读取 InputStream,解析响应体
301 / 302 重定向 HttpURLConnection 默认自动跟随,无需手动处理
400 请求参数错误 检查 URL 与请求头,提示用户
401 / 403 未授权 / 禁止访问 检查 Token 或权限配置
404 资源不存在 确认接口路径是否正确
500 服务端内部错误 提示用户稍后重试,记录日志