在移动网络环境下,资源加载延迟直接决定用户体验。对于依赖高清图片、短视频或大文件下载的鸿蒙应用,传统“即用即拉”模式在遭遇网络波动、DNS劫持或CDN节点劣化时,容易引发白屏、卡顿甚至超时。HarmonyOS NEXT 6.1 (API 23) 对 Basic Service Kit 的 cacheDownload 模块进行了重要升级,新增 NetworkInfo.ip 属性用于获取对端服务器物理IP,同时提供 dnsServers 列表和7维毫秒级性能瀑布流。本文将基于实际工程,详解如何利用这些能力构建预下载缓存机制与网络诊断功能。
- // 关键API声明(来自@kit.BasicServicesKit)
- import { cacheDownload } from '@kit.BasicServicesKit';
- // cacheDownload.download 用于预下载资源
- function download(url: string, options: CacheDownloadOptions): void;
- // CacheStrategy 缓存策略:FORCE(0)强制重下,LAZY(1)仅在缓存不存在时下载
- // 权限要求:ohos.permission.INTERNET
- // 新增 NetworkInfo 接口(API 23)
- interface NetworkInfo {
- readonly dnsServers: string[]; // DNS服务器IP列表
- readonly ip?: string; // 对端服务器IP(新增,DNS失败时为undefined)
- }
- // 获取info需权限:ohos.permission.GET_NETWORK_INFO
- // PerformanceInfo 提供各阶段耗时(单位ms)
- // dnsTime, connectTime, tlsTime, firstReceiveTime, redirectTime, totalTime
复制代码
## 工程结构与权限配置
创建一个标准ArkTS工程(如BasicServiceKitDemo),在 entry/src/main/resources/base/profile/main_pages.json 中注册两个页面:Index.ets(引导页)和 BasicServiceDemo.ets(主控制舱)。在 module.json5 中必须添加网络权限:- // module.json5
- "requestPermissions": [
- {
- "name": "ohos.permission.INTERNET"
- },
- {
- "name": "ohos.permission.GET_NETWORK_INFO"
- }
- ]
复制代码 注意:GET_NETWORK_INFO 权限用于获取对端IP和DNS服务器列表,属于敏感权限,需在真机或授权模拟器上运行。
## 预下载核心逻辑(BasicServiceDemo.ets)
控制舱页面实现了以下核心功能:
1. 输入资源URL,发起预下载任务(使用LAZY策略避免重复拉取)
2. 注册成功/失败回调,实时更新下载状态
3. 下载成功后调用 cacheDownload.getDownloadInfo 提取网络信息与性能指标
4. 动态调整内存/文件缓存大小,支持一键清空缓存
### 开始预下载- startPreDownload() {
- if (!this.downloadUrl || !this.downloadUrl.startsWith('http')) {
- promptAction.showToast({ message: '请输入合法链接' });
- return;
- }
- this.isDownloading = true;
- this.downloadStatus = '下载中...';
- this.hasInfo = false;
- // 先注销旧监听避免重复触发
- cacheDownload.offDownloadSuccess(this.downloadUrl);
- cacheDownload.offDownloadError(this.downloadUrl);
- // 注册成功回调
- cacheDownload.onDownloadSuccess(this.downloadUrl, () => {
- this.isDownloading = false;
- this.downloadStatus = '成功';
- this.queryTaskInfo(); // 成功立即查询网络信息
- });
- // 注册失败回调
- cacheDownload.onDownloadError(this.downloadUrl, (err) => {
- this.isDownloading = false;
- this.downloadStatus = '失败';
- this.lastErrorMsg = `ErrorCode: ${err.errorCode}, Msg: ${err.message}`;
- });
- // 执行下载,使用LAZY策略
- cacheDownload.download(this.downloadUrl, {
- cacheStrategy: cacheDownload.CacheStrategy.LAZY
- });
- }
复制代码
### 提取网络诊断信息
成功回调中调用 queryTaskInfo 获取对端IP、DNS服务器列表和性能指标。注意 ip 属性可能为 undefined(DNS失败或低API版本),需使用空值合并运算符 ?? 进行安全防错:- queryTaskInfo() {
- try {
- let info = cacheDownload.getDownloadInfo(this.downloadUrl);
- if (!info) {
- // 无历史记录(可能被系统回收或尚未成功)
- return;
- }
- this.dnsServers = info.network.dnsServers;
- this.resolvedIp = info.network.ip ?? '解析失败/未获取';
- this.decompressedSize = info.resource.size;
- this.dnsTime = info.performance.dnsTime;
- this.connectTime = info.performance.connectTime;
- this.tlsTime = info.performance.tlsTime;
- this.firstReceiveTime = info.performance.firstReceiveTime;
- this.totalTime = info.performance.totalTime;
- this.redirectTime = info.performance.redirectTime;
- } catch (e) {
- let err = e as BusinessError;
- if (err.code === 201) {
- // 缺少GET_NETWORK_INFO权限
- }
- }
- }
复制代码
### 缓存额度治理
支持动态调整系统分配给应用的内存缓存和文件缓存上限,以及一键清空:- applyCacheSizes() {
- let memSize = parseInt(this.memoryCacheSizeInput);
- let fileSize = parseInt(this.fileCacheSizeInput);
- cacheDownload.setMemoryCacheSize(memSize);
- cacheDownload.setFileCacheSize(fileSize);
- }
- clearAllCaches() {
- cacheDownload.clearMemoryCache();
- cacheDownload.clearFileCache();
- }
复制代码
## 关键注意事项
- **空安全**:info.network.ip 在 HarmonyOS 严格要求 null-safety 编译环境下需用 `??` 降级,否则编译报错。
- **权限合规**:GET_NETWORK_INFO 属于敏感权限,需在 module.json5 声明,并在运行时检查。若缺少,getDownloadInfo 会抛出 code 201 异常。
- **性能指标含义**:firstReceiveTime 即 TTFB(首包接收耗时),是衡量CDN节点质量的关键指标;tlsTime 反映TLS握手性能,在弱网或证书链长时可能显著增加。
- **缓存策略选择**:LAZY 适用于首次下载后不再更新的静态资源;FORCE 适用于需要强制刷新缓存的场景(如配置文件更新)。
## 实战效果
通过上述控制舱,开发者可以直观看到:
- 预下载任务的状态机流转(待触发→下载中→成功/失败/已取消)
- 成功连接的对端物理IP地址(突破DNS黑盒)
- 当前解析使用的DNS服务器列表(诊断DNS劫持)
- 各阶段耗时瀑布流(定位是DNS慢还是TCP建连慢)
- 缓存占用实时可调、可清
这套预下载机制尤其适合图片/视频类应用,在用户进入页面之前静默拉取资源,结合网络诊断数据可自选最优CDN节点或切换备用域名,显著提升加载速度。开发者可基于本篇示例代码快速集成,只需替换资源URL并调整缓存策略即可投入生产环境。 |