1. Android网络请求基础概念
在Android开发中,网络请求是与服务器交互的核心方式。GET请求作为HTTP协议中最基础的请求方法,主要用于从服务器获取数据。与POST请求不同,GET请求的参数会直接附加在URL后面,这使得它更适合用于查询操作而非数据提交。
Android平台提供了多种实现GET请求的方式,从最基础的HttpURLConnection到流行的第三方库如Retrofit。选择哪种方式取决于项目复杂度、团队技术栈和维护需求等因素。
注意:从Android 9.0(API级别28)开始,默认情况下禁止明文HTTP流量。如果必须使用HTTP而非HTTPS,需要在AndroidManifest.xml中配置网络安全策略。
2. 使用HttpURLConnection实现GET请求
2.1 基本实现步骤
HttpURLConnection是Java标准库提供的HTTP客户端,也是Android中最基础的网络请求实现方式。以下是完整实现代码:
public class HttpUtils { public static String get(String urlString) throws IOException { URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); try { connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); connection.setReadTimeout(5000); int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = connection.getInputStream(); BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream)); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } return response.toString(); } else { throw new IOException("HTTP error code: " + responseCode); } } finally { connection.disconnect(); } } }2.2 关键参数解析
setConnectTimeout(5000):设置连接超时为5秒,防止网络状况不佳时长时间等待setReadTimeout(5000):设置读取超时为5秒,确保服务器响应不及时时能够及时中断HTTP_OK(状态码200):表示请求成功finally块中的disconnect():确保无论请求成功与否都会释放连接资源
2.3 异步处理方案
由于Android禁止在主线程执行网络操作,必须使用异步任务:
new AsyncTask<String, Void, String>() { @Override protected String doInBackground(String... urls) { try { return HttpUtils.get(urls[0]); } catch (IOException e) { return "Error: " + e.getMessage(); } } @Override protected void onPostExecute(String result) { // 更新UI } }.execute("https://api.example.com/data");3. 使用OkHttp实现GET请求
3.1 OkHttp基础配置
OkHttp是Square公司开发的HTTP客户端,相比HttpURLConnection提供了更简洁的API和更强大的功能。首先添加依赖:
implementation 'com.squareup.okhttp3:okhttp:4.9.3'基础GET请求实现:
OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() .url("https://api.example.com/data?id=123") .build(); try (Response response = client.newCall(request).execute()) { if (response.isSuccessful()) { String responseData = response.body().string(); // 处理响应数据 } }3.2 高级特性
OkHttp支持许多实用功能:
- 拦截器:可以添加日志拦截器监控请求/响应
client = new OkHttpClient.Builder() .addInterceptor(new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY)) .build();- 缓存控制:配置缓存策略减少网络请求
int cacheSize = 10 * 1024 * 1024; // 10MB Cache cache = new Cache(context.getCacheDir(), cacheSize); client = new OkHttpClient.Builder() .cache(cache) .build();- 超时设置:针对不同环节设置超时
client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .writeTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) .build();4. 使用Retrofit实现GET请求
4.1 Retrofit基础配置
Retrofit是Square开发的类型安全的HTTP客户端,基于OkHttp。添加依赖:
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-gson:2.9.0'定义API接口:
public interface ApiService { @GET("data") Call<ResponseData> getData(@Query("id") String id); }创建Retrofit实例:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.example.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); ApiService service = retrofit.create(ApiService.class);4.2 请求执行与响应处理
同步请求:
Response<ResponseData> response = service.getData("123").execute(); if (response.isSuccessful()) { ResponseData data = response.body(); // 处理数据 }异步请求:
service.getData("123").enqueue(new Callback<ResponseData>() { @Override public void onResponse(Call<ResponseData> call, Response<ResponseData> response) { if (response.isSuccessful()) { // 更新UI } } @Override public void onFailure(Call<ResponseData> call, Throwable t) { // 处理错误 } });4.3 高级URL配置
Retrofit支持多种URL配置方式:
- 路径参数:
@GET("user/{id}") Call<User> getUser(@Path("id") String userId);- 查询参数:
@GET("search") Call<SearchResult> search(@Query("q") String query);- 多个查询参数:
@GET("search") Call<SearchResult> search(@QueryMap Map<String, String> filters);5. 网络请求常见问题与优化
5.1 性能优化技巧
- 连接复用:OkHttp默认启用连接池,保持连接活跃状态
- 数据压缩:添加
Accept-Encoding: gzip头减少传输数据量 - 缓存策略:合理配置缓存减少重复请求
- 批量请求:合并多个小请求为一个批量请求
5.2 常见错误处理
- SSL证书问题:
OkHttpClient client = new OkHttpClient.Builder() .hostnameVerifier((hostname, session) -> true) .sslSocketFactory(createSSLSocketFactory(), createTrustManager()) .build();- JSON解析异常:使用Gson的
TypeAdapter处理特殊数据类型 - 空响应体:检查
response.body()是否为null - 线程切换:使用Handler或LiveData将结果传回主线程
5.3 调试技巧
- 使用Stetho:Facebook开发的调试工具,可以查看网络请求
implementation 'com.facebook.stetho:stetho:1.6.0' implementation 'com.facebook.stetho:stetho-okhttp3:1.6.0'- 日志拦截器:详细记录请求和响应数据
- 模拟API响应:使用MockWebServer进行单元测试
6. 现代Android网络请求最佳实践
6.1 结合协程使用
Retrofit支持协程方式调用:
@GET("data") suspend fun getData(@Query("id") id: String): Response<ResponseData> // 调用 viewModelScope.launch { try { val response = apiService.getData("123") if (response.isSuccessful) { // 更新UI } } catch (e: Exception) { // 处理错误 } }6.2 结合Jetpack组件
- Repository模式:
public class DataRepository { private ApiService apiService; public LiveData<Result<ResponseData>> getData(String id) { MutableLiveData<Result<ResponseData>> result = new MutableLiveData<>(); apiService.getData(id).enqueue(new Callback<ResponseData>() { // 处理响应 }); return result; } }- 使用WorkManager处理后台请求:
Constraints constraints = new Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build(); OneTimeWorkRequest request = new OneTimeWorkRequest.Builder( NetworkWorker.class) .setConstraints(constraints) .build(); WorkManager.getInstance(context).enqueue(request);6.3 安全建议
- 使用HTTPS:始终优先使用HTTPS而非HTTP
- 证书锁定:配置Certificate Pinning防止中间人攻击
- 敏感数据:不要在URL中传递敏感信息
- 权限控制:检查
android.permission.INTERNET权限
在实际项目中,我通常会根据项目规模选择网络库。对于小型项目,OkHttp已经足够;中型项目使用Retrofit可以提高开发效率;大型项目则需要结合协程和架构组件构建完整的网络层。无论选择哪种方式,良好的错误处理和日志记录都是必不可少的。