深入浅出安卓深度网络优化
一、网络请求为什么慢?
想象你的App是个外卖小哥,网络慢可能因为:
- DNS解析慢(找餐厅花了10分钟)
- 连接建立慢(餐厅门口排队)
- 数据传输慢(打包饭菜太慢)
- 重复跑腿(相同订单送两次)
二、网络优化核心指标
| 指标 | 理想值 | 检测方法 |
|---|---|---|
| DNS时间 | <200ms | Charles抓包 |
| TCP连接时间 | <300ms | Android Profiler |
| SSL握手时间 | <400ms | adb logcat |
| 首包时间 | <500ms | Network Monitor |
| 下载速度 | >1Mbps | 测速工具 |
三、六大深度优化方案
1. DNS优化(找餐厅更快)
问题:默认DNS可能绕路
// 传统DNS解析(可能慢)
HttpURLConnection.connect();
解决方案:
// 使用HTTPDNS(阿里云/腾讯云提供)
String ip = HTTPDNS.getIpByHost("api.example.com");
URL url = new URL("https://" + ip + "/path");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Host", "api.example.com"); // 关键!
效果:DNS时间从500ms降到50ms
2. 连接复用(不用每次都排队)
错误示范:
// 每次请求新建连接(浪费资源)
for (int i=0; i<10; i++) {
HttpURLConnection conn = new HttpURLConnection(url);
conn.connect();
}
正确做法:
// OkHttp自动连接池(默认开启)
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(url).build();
client.newCall(request).enqueue(callback); // 自动复用连接
数据:减少50%的TCP握手时间
3. 数据压缩(少搬点货)
未压缩请求:
GET /api/data HTTP/1.1
Host: example.com
User-Agent: Dalvik/2.1.0
Accept: */*
压缩后请求:
GET /api/data HTTP/1.1
Host: example.com
Accept-Encoding: gzip, deflate // 关键头
服务端返回:
HTTP/1.1 200 OK
Content-Encoding: gzip // 压缩标识
效果:JSON数据从100KB→20KB
4. 智能重试(送餐失败策略)
基础重试(不够智能):
// 简单重试3次
for (int i=0; i<3; i++) {
try {
makeRequest();
break;
} catch (IOException e) {
Thread.sleep(1000);
}
}
高级重试(Retrofit+OkHttp):
OkHttpClient client = new OkHttpClient.Builder()
.retryOnConnectionFailure(true) // 自动重试
.addInterceptor(new RetryInterceptor(3)) // 自定义拦截器
.build();
// 拦截器实现
class RetryInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
// 对5xx错误和IO异常重试
for (int i=0; i<maxRetry; i++) {
try {
return chain.proceed(request);
} catch (IOException e) {
if (i == maxRetry-1) throw e;
Thread.sleep(1000);
}
}
return null;
}
}
5. 协议升级(走高速路)
HTTP/1.1问题:
- 队头阻塞(前一个请求卡住后面所有请求)
- 每个域名最多6个连接
HTTP/2优势:
- 多路复用(一个连接并行多个请求)
- 头部压缩
- 服务器推送
启用方法:
OkHttpClient client = new OkHttpClient.Builder()
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1)) // 优先HTTP/2
.build();
6. 弱网优化(电梯里也能用)
策略组合:
- 缓存兜底:显示旧数据同时加载新数据
// Retrofit缓存策略 @GET("user/info") @Headers("Cache-Control: max-stale=3600") // 1小时陈旧数据可用 Call<UserInfo> getUserInfo(); - 增量更新:只获取变化部分
// 传统接口 {"data": [完整数据]} // 增量接口 {"patch": [差异数据], "version": 123} - 长短连接结合:重要请求用长连接
// WebSocket保持连接 OkHttpClient client = new OkHttpClient.Builder() .pingInterval(30, TimeUnit.SECONDS) // 心跳保活 .build();
四、网络监控体系
1. 客户端监控
// OkHttp事件监听
class NetworkEventListener extends EventListener {
@Override
public void callStart(Call call) {
startTime = System.currentTimeMillis();
}
@Override
public void callEnd(Call call) {
reportToServer("api_duration", System.currentTimeMillis() - startTime);
}
}
2. 关键指标看板
| 指标 | 报警阈值 | 优化目标 |
|---|---|---|
| 请求成功率 | <99% | >99.5% |
| P90耗时 | >2000ms | <1000ms |
| 慢请求比例 | >5% | <1% |
五、特殊场景优化
1. 文件上传
错误做法:
// 直接上传原图(10MB)
RequestBody body = RequestBody.create(MediaType.parse("image/*"), file);
正确方案:
// 先压缩再上传(200KB)
Bitmap compressed = BitmapUtil.compress(file, 200);
RequestBody body = new MultipartBody.Builder()
.addFormDataPart("file", "avatar.jpg",
RequestBody.create(MediaType.parse("image/jpeg"), compressed))
.build();
2. 离线模式
// 使用Room缓存网络数据
@Dao
interface UserDao {
@Query("SELECT * FROM user WHERE id = :userId")
fun getUser(userId: String): LiveData<User>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun saveUser(user: User)
}
// 网络请求后自动更新数据库
fun fetchUser(userId: String) {
val user = apiService.getUser(userId)
userDao.saveUser(user)
}
六、避坑指南
1. 不要信任所有网络
// 检测网络质量
ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
NetworkCapabilities nc = cm.getNetworkCapabilities(cm.getActiveNetwork());
boolean isMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); // 是否计费网络
// 大文件只在WiFi下下载
if (!isMetered) {
startBigDownload();
}
2. 小心缓存失控
// 正确设置缓存大小(10MB)
Cache cache = new Cache(cacheDir, 10 * 1024 * 1024);
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
七、优化效果对比
| 优化前 | 优化后 | 提升幅度 |
|---|---|---|
| 平均请求耗时2000ms | 800ms | 60% |
| 流量消耗50MB/天 | 15MB/天 | 70% |
| 弱网成功率30% | 75% | 150% |
八、终极优化口诀
"DNS要快,连接要复,
数据要压,重试要智,
协议要新,弱网要顾,
监控要全,异常要知"
把这些做到位,你的App网络就能快如闪电!⚡