核心流程
无论使用哪种方法,获取网络 JSON 数据的基本流程都遵循以下步骤:

- 添加网络权限:在
AndroidManifest.xml中声明需要访问网络的权限。 - 创建网络请求:指定 URL,使用 HTTP 客户端(如
HttpURLConnection或第三方库)向服务器发送请求。 - 获取响应:读取服务器返回的数据流。
- 解析 JSON:使用 JSON 解析库(如
org.json或 Gson)将字符串数据解析成 Java 对象。 - 更新 UI:将解析后的数据在主线程(UI 线程)上展示给用户。
使用 HttpURLConnection (原生 API)
这是最基础的方法,不需要引入第三方库,适合学习网络请求的基本原理。
添加网络权限
在 app/src/main/AndroidManifest.xml 文件中,在 <application> 标签之前添加:
<uses-permission android:name="android.permission.INTERNET" />
添加网络安全配置 (Android 9.0+)
从 Android 9 (API 28) 开始,默认禁止使用 HTTP 明文传输,如果你的 API 是 http 开头的,需要在 res/xml/network_security_config.xml 中配置:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">your-api-domain.com</domain>
</domain-config>
</network-security-config>
然后在 AndroidManifest.xml 的 <application> 标签中引用它:

<application
...
android:networkSecurityConfig="@xml/network_security_config"
...>
...
</application>
提示:对于学习或内部测试,可以直接在
<application>标签中添加android:usesCleartextTraffic="true",但这不推荐用于生产环境。
编写网络请求代码
重要:网络操作不能在主线程(UI 线程)中进行,否则会抛出 NetworkOnMainThreadException 异常,我们必须使用异步任务,Thread + Handler、AsyncTask (已废弃)、ExecutorService 或现代的 Kotlin Coroutines/RxJava。
这里我们使用 ExecutorService + Handler 的方式,因为它清晰且易于理解。
示例代码:

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private static final String JSON_URL = "https://api.publicapis.org/random"; // 示例 API
private TextView textViewResult;
private ExecutorService executorService;
private Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewResult = findViewById(R.id.text_view_result);
executorService = Executors.newSingleThreadExecutor(); // 创建一个单线程的线程池
handler = new Handler(Looper.getMainLooper()); // 创建一个与主线程关联的 Handler
// 在后台线程执行网络请求
executorService.execute(() -> {
try {
String jsonResponse = makeHttpRequest(new URL(JSON_URL));
// 在主线程更新 UI
handler.post(() -> {
textViewResult.setText(jsonResponse);
Toast.makeText(MainActivity.this, "数据加载成功", Toast.LENGTH_SHORT).show();
});
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
// 在主线程显示错误信息
handler.post(() -> Toast.makeText(MainActivity.this, "网络请求失败", Toast.LENGTH_SHORT).show());
}
});
}
private String makeHttpRequest(URL url) throws IOException {
String jsonResponse = "";
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
BufferedReader reader = null;
try {
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setConnectTimeout(15000); // 15秒连接超时
urlConnection.setReadTimeout(15000); // 15秒读取超时
urlConnection.connect();
if (urlConnection.getResponseCode() == 200) { // HTTP 200 OK
inputStream = urlConnection.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder buffer = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
jsonResponse = buffer.toString();
} else {
Log.e(TAG, "Error response code: " + urlConnection.getResponseCode());
}
} catch (IOException e) {
Log.e(TAG, "IOException: " + e.getMessage());
} finally {
// 确保流和连接被关闭
if (reader != null) reader.close();
if (inputStream != null) inputStream.close();
if (urlConnection != null) urlConnection.disconnect();
}
return jsonResponse;
}
@Override
protected void onDestroy() {
super.onDestroy();
// 关闭线程池,防止内存泄漏
executorService.shutdown();
}
}
使用现代库 (推荐)
原生 HttpURLConnection 代码冗长且容易出错,在现代 Android 开发中,我们强烈推荐使用第三方库来简化网络请求。
方案 A:Retrofit + Gson (Java/Kotlin)
这是目前最流行、最强大的组合,Retrofit 负责处理网络请求,Gson 负责解析 JSON。
添加依赖
在 app/build.gradle 文件中添加:
dependencies {
// Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Gson 转换器
// OkHttp (Retrofit 的默认依赖)
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3' // 用于打印日志
}
添加网络权限和配置 (与方法一相同)
创建数据模型
根据你的 JSON 结构创建 Java/Kotlin 类。
示例 JSON:
{
"count": 1,
"entries": [
{
"API": "Yes or No",
"Description": "Get a random yes/no answer to a question",
"Auth": "No",
"HTTPS": true,
"Cors": "unknown",
"Link": "https://yesno.wtf/api",
"Category": "Development"
}
]
}
Java 数据模型:
// Entry.java
public class Entry {
public String API;
public String Description;
public String Auth;
public boolean HTTPS;
public String Cors;
public String Link;
public String Category;
}
// RandomApi.java
public class RandomApi {
public int count;
public List<Entry> entries;
}
创建 Retrofit 接口
定义你的 API 端点。
import retrofit2.Call;
import retrofit2.http.GET;
public interface ApiService {
@GET("random") // API 的路径
Call<RandomApi> getRandomData();
}
执行请求并更新 UI
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private TextView textViewResult;
private ApiService apiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textViewResult = findViewById(R.id.text_view_result);
// 1. 创建 Retrofit 实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.publicapis.org/") // API 的基础 URL
.addConverterFactory(GsonConverterFactory.create()) // 添加 Gson 转换器
.build();
// 2. 创建 API 接口的实例
apiService = retrofit.create(ApiService.class);
// 3. 发起异步请求
apiService.getRandomData().enqueue(new Callback<RandomApi>() {
@Override
public void onResponse(Call<RandomApi> call, Response<RandomApi> response) {
if (response.isSuccessful() && response.body() != null) {
RandomApi randomApi = response.body();
List<Entry> entries = randomApi.entries;
if (!entries 