18、Android性能优化之网络优化:数据压缩(Gzip)、请求合并、缓存策略、DNS优化

网络优化,说白了就是让App在用户手机上和服务器“少说话、说短话、说有用的话”。

我刚开始做Android开发那会儿,总觉得网络请求能通就行。直到有一次,用户反馈App在2G/3G网络下卡得像个PPT,我才意识到——网络优化不是锦上添花,而是雪中送炭。

今天咱们就聊聊网络优化的四个核心方向:数据压缩、请求合并、缓存策略、DNS优化。这四个点,你吃透了,App的网络性能至少能提升一个档次。

网络优化四大方向 数据压缩 Gzip / 图片WebP 请求合并 批量接口 / 队列 缓存策略 内存 / 磁盘 / 离线 DNS优化 预解析 / HTTPDNS 核心目标:减少传输量 + 减少请求次数 + 减少等待时间

1. 数据压缩:让传输的每一字节都值钱

数据压缩,说白了就是让服务器和App之间传的数据“瘦身”。

Gzip压缩是业界最常用的方式。你想想看,一个JSON接口返回几百KB,Gzip一压可能就剩几十KB。我习惯在OkHttp的拦截器里统一开启Gzip,这样所有请求都自动受益。

核心要点: 服务端返回时设置 Content-Encoding: gzip,客户端自动解压。OkHttp默认支持,但记得在请求头里加 Accept-Encoding: gzip
// OkHttp 全局开启 Gzip(其实默认就支持,但显式设置更保险)
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(chain -> {
        Request originalRequest = chain.request();
        Request compressedRequest = originalRequest.newBuilder()
                .header("Accept-Encoding", "gzip")
                .build();
        return chain.proceed(compressedRequest);
    })
    .build();

除了Gzip,图片压缩也很关键。我在项目中遇到过,一个列表页加载20张高清图,流量直接爆炸。后来统一用WebP格式,体积平均减少30%以上。Android从4.0就开始支持WebP了,放心用。

我的小技巧: 对于非实时性数据(比如用户头像、商品图片),可以在服务端预压缩成WebP,客户端直接展示。既省流量又省CPU。

2. 请求合并:别让App“频繁眨眼”

你有没有遇到过这种情况?一个页面刚打开,瞬间发起七八个网络请求。每个请求都有TCP握手、TLS协商、数据传输……加起来耗时翻倍。

我建议的做法是:把多个小请求合并成一个批量接口。比如首页需要用户信息、推荐列表、公告,完全可以合并成一个 /home/page 接口,一次性返回所有数据。

如果后端不支持合并,客户端也可以做“请求队列”。我记得在做一个社交App时,点赞、关注、评论这些操作,我让它们先在本地排队,每500ms或攒够5条再统一发送。效果立竿见影,服务器压力小了,用户也觉得更流畅。

注意: 请求合并不是万能的。实时性要求高的操作(比如支付、验证码)必须单独发送。合并只适合那些“晚几秒也无所谓”的数据。

3. 缓存策略:让数据“随叫随到”

缓存,是网络优化里性价比最高的手段。没有之一。

我习惯把缓存分为三层:内存缓存、磁盘缓存、离线缓存

缓存层级 速度 容量 典型实现
内存缓存 纳秒级 小(几MB) LruCache
磁盘缓存 毫秒级 大(几十MB) DiskLruCache / OkHttp Cache
离线缓存 秒级(需加载) 视情况而定 Room / SQLite

OkHttp自带的缓存机制非常强大。你只需要配置一个Cache目录和大小,它就会自动根据响应头(Cache-Control、ETag、Last-Modified)来决定是否缓存、是否使用缓存。

// OkHttp 磁盘缓存配置
int cacheSize = 10 * 1024 * 1024; // 10 MB
Cache cache = new Cache(cacheDir, cacheSize);

OkHttpClient client = new OkHttpClient.Builder()
    .cache(cache)
    .build();

这里有个坑:服务端必须正确返回缓存相关的响应头。我曾经遇到一个项目,客户端配了缓存,但服务端每次返回 Cache-Control: no-cache,结果缓存形同虚设。后来我跟后端同学沟通,统一改成 Cache-Control: max-age=3600,问题才解决。

避坑指南: 如果你发现OkHttp缓存不生效,先抓包看看响应头。八成是服务端没配好,或者配了 no-cache

4. DNS优化:别让“查地址”拖慢网速

DNS解析,说白了就是把域名翻译成IP地址。这个过程虽然快,但每次请求都要做一次,而且可能被运营商劫持、解析慢、甚至返回错误IP。

我推荐两个优化手段:DNS预解析HTTPDNS

DNS预解析:在App启动时或者空闲时,提前把常用域名解析好,缓存起来。这样真正请求时直接拿IP,省去DNS查询时间。

// 使用 OkHttp 的 Dns 接口做预解析
OkHttpClient client = new OkHttpClient.Builder()
    .dns(new Dns() {
        @Override
        public List<InetAddress> lookup(String hostname) throws UnknownHostException {
            // 先从本地缓存查,查不到再走系统DNS
            List<InetAddress> cached = cache.get(hostname);
            if (cached != null) return cached;
            List<InetAddress> result = Dns.SYSTEM.lookup(hostname);
            cache.put(hostname, result);
            return result;
        }
    })
    .build();

HTTPDNS:直接使用HTTP协议向专门的DNS服务器查询IP,绕过运营商DNS,避免劫持和解析慢的问题。阿里云、腾讯云都有现成的HTTPDNS服务。我曾在海外项目中使用过,效果很明显,解析成功率从95%提升到99.5%以上。

我的经验: 如果App只在国内使用,HTTPDNS不是必须的。但如果你的App有海外用户,或者经常遇到DNS劫持,HTTPDNS绝对是值得投入的优化点。

总结一下

网络优化,其实就四个字:少、快、准、省

  • :数据压缩,减少传输量
  • :请求合并,减少请求次数
  • :缓存策略,减少重复请求
  • :DNS优化,减少等待时间

这四个方向,你不需要一次性全部做完。先从最容易的Gzip和缓存入手,效果立竿见影。等遇到瓶颈了,再考虑请求合并和HTTPDNS。

嗯,网络优化这块,说到底就是让用户感觉“快”。用户不会关心你用了什么技术,他只关心App是不是秒开、刷视频是不是流畅。咱们做开发的,就是要在背后把这些细节做到位。

公众号:蓝海资料掘金营,微信deep3321