性能优化:扫描间隔控制、连接速度优化、内存与 CPU 占用
Wi-Fi 性能优化,说白了就是让系统跑得又快又稳。我见过不少项目,功能都做全了,但一跑起来手机发烫、电量狂掉。用户可不管你是不是功能完整,卡顿就是原罪。
今天咱们就聊聊三个核心方向:扫描间隔怎么控、连接速度怎么提、内存和 CPU 怎么省。嗯,这些都是我在实际项目中踩过的坑。
扫描间隔控制:别让 Wi-Fi 像个永动机
Wi-Fi 扫描是个耗电大户。你想想看,每次扫描都要唤醒天线、监听信道、解析 beacon 帧。如果扫描太频繁,电池扛不住。但如果扫描间隔太长,用户又觉得 Wi-Fi 反应慢。
核心原则:按需扫描,动态调整。
我个人习惯把扫描场景分成三类:
- 前台场景:用户正在操作 Wi-Fi 界面,或者正在连接网络。这时候需要快速响应,扫描间隔可以短到 3-5 秒。
- 后台场景:应用在后台运行,或者屏幕关闭。这时候可以拉长到 30-60 秒,甚至更久。
- 漫游场景:设备在移动中,信号强度在下降。这时候需要主动触发扫描,而不是等固定间隔。
避坑指南:我曾经在一个项目中,把后台扫描间隔设成了 10 秒。结果用户反馈手机半天就没电了。后来一查,Wi-Fi 扫描占了 30% 的耗电。改成 60 秒后,问题直接解决。
代码实现上,我建议用 WifiManager.startScan() 配合定时器,而不是依赖系统默认的扫描周期。这样你可以根据场景动态调整:
// 动态扫描间隔示例
private static final long SCAN_INTERVAL_FOREGROUND = 5_000L; // 5秒
private static final long SCAN_INTERVAL_BACKGROUND = 60_000L; // 60秒
private void scheduleScan(long interval) {
mHandler.removeCallbacks(mScanRunnable);
mHandler.postDelayed(mScanRunnable, interval);
}
private final Runnable mScanRunnable = new Runnable() {
@Override
public void run() {
mWifiManager.startScan();
// 根据当前场景决定下一次扫描间隔
long nextInterval = isForeground() ?
SCAN_INTERVAL_FOREGROUND : SCAN_INTERVAL_BACKGROUND;
scheduleScan(nextInterval);
}
};
连接速度优化:从扫描到连上,能多快就多快
用户最烦的是什么?点开 Wi-Fi 列表,等半天才看到网络列表。选了个网络,又等半天才连上。这体验,说实话挺糟糕的。
连接速度优化,我总结了三板斧:
- 缓存已知网络:别每次都全量扫描。如果用户之前连过某个网络,直接缓存它的 BSSID、信道、加密方式。下次连接时,优先尝试缓存的信息。
- 并行扫描与认证:扫描和认证可以同时进行。我记得在 Android 8.0 之后,系统支持了
WifiNetworkSpecifier,可以提前指定网络参数,跳过扫描阶段。 - 减少不必要的信令交互:DHCP 协商、4-way handshake 这些步骤,能省则省。比如用静态 IP 代替 DHCP,或者缓存 PMKID 避免重复认证。
小技巧:我习惯在 WifiManager 的 CONNECT_NETWORK 回调中,直接监听 SUPPLICANT_STATE_CHANGE_ACTION。这样能第一时间知道连接状态,不用等系统广播绕一圈。
来看一个实际优化案例。有一次,我发现某个设备连接企业级 Wi-Fi 特别慢,每次都要 8-10 秒。后来定位到是 EAP 认证时,证书验证花了太多时间。优化方案是缓存 CA 证书的哈希值,避免每次都重新解析:
// 缓存 EAP 证书信息,加速重连
private static final String CACHED_CA_HASH = "sha256/...";
private boolean verifyCachedCertificate(X509Certificate cert) {
String hash = computeHash(cert.getEncoded());
return CACHED_CA_HASH.equals(hash);
}
优化后,连接时间降到了 2-3 秒。用户反馈明显变好了。
内存与 CPU 占用:别让 Wi-Fi 服务成为性能杀手
Wi-Fi Service 跑在系统进程中,如果它占用了太多内存或 CPU,整个系统都会变慢。我见过最夸张的情况,Wi-Fi 进程占用了 200MB 内存,导致系统频繁触发 low memory killer。
内存优化要点:
- 避免大对象常驻:比如扫描结果列表,每次扫描后及时清理旧数据。我习惯用
WeakReference来持有扫描结果,避免强引用导致内存泄漏。 - 复用对象:像
ScanResult、WifiConfiguration这些对象,能复用就复用。别每次 new 一个新的。 - 延迟加载:有些数据不是一开始就需要。比如网络历史记录,可以等用户打开 Wi-Fi 设置页面时再加载。
CPU 优化要点:
- 减少轮询:能用回调就别用轮询。比如监听
RSSI_CHANGED_ACTION代替定时检查信号强度。 - 批量处理:如果有多个网络需要连接,别一个一个来。批量提交给 supplicant,让它自己调度。
- 异步处理:耗时的操作(比如 DHCP、DNS 查询)放到后台线程。别在主线程里等。
注意:我曾经在优化 CPU 占用时,把扫描结果的处理放到了 AsyncTask 里。结果因为线程池太小,导致扫描结果处理排队,反而更慢了。后来改用 HandlerThread 单独开一个线程,才解决问题。
下面这张图是我自己总结的 Wi-Fi 性能优化整体框架,你可以参考一下:
实战中的取舍
说实话,性能优化没有银弹。你不可能同时做到扫描最快、连接最快、资源占用最低。关键是根据产品定位做取舍。
举个例子:
- 如果是 手机,电池续航优先,扫描间隔可以拉长。
- 如果是 智能家居设备,连接速度优先,可以牺牲一点功耗。
- 如果是 车载系统,稳定性优先,内存占用要严格控制。
我个人的经验是:先定指标,再优化。比如设定「扫描到连接完成不超过 3 秒」、「Wi-Fi 进程内存占用不超过 50MB」、「CPU 占用率不超过 5%」。有了明确的目标,优化起来才有方向。
最后说一句:性能优化是个持续的过程。别指望一次改完就万事大吉。上线后多看看日志,多听听用户反馈。有时候一个小改动,就能带来质的提升。
公众号:蓝海资料掘金营,微信deep3321