HarmonyOS APP开发:Network Profiler与网络请求分析
HarmonyOS APP开发:Network Profiler与网络请求分析
📌 核心要点:Network Profiler帮你透视每一个HTTP请求的完整生命周期——从DNS解析到数据传输,精准定位网络瓶颈,让"请求为什么这么慢"不再靠猜。
一、背景与动机
你有没有遇到过这种情况:App打开后白屏好几秒,最后数据才慢慢加载出来?用户第一反应是"这App太垃圾了",但作为开发者的你却很委屈——后端接口响应明明只要200ms,那剩下的几秒都花在哪了?
网络请求的耗时是一个"黑箱"——从你调用http.request()到收到响应,中间经历了DNS解析、TCP握手、TLS协商、请求发送、服务端处理、响应传输、数据解析等十几个环节。任何一个环节出问题,都会拖慢整体耗时。但问题是,你只看得到总耗时,看不到每个环节花了多少时间。
Network Profiler就是来帮你拆解这个黑箱的。它像一台网络"慢动作回放机",把每个请求的每个阶段都拆开给你看——DNS解析花了多久?TCP连接建立花了多久?服务端处理花了多久?响应体有多大?传输花了多久?一目了然。
更关键的是,Network Profiler还能帮你发现一些"隐形"的网络问题:比如同一个接口被重复调用了3次、图片没有压缩导致流量暴增、HTTPS证书配置错误导致每次都要重新握手……这些问题用户感知不到,但它们在悄悄吞噬你的App体验。
二、核心原理
2.1 HTTP请求的完整生命周期
理解Network Profiler的前提是理解HTTP请求的完整生命周期:
graph TD
A[发起HTTP请求]:::primary --> B[DNS解析<br>域名→IP地址]:::info
B --> C[TCP三次握手<br>建立连接]:::info
C --> D{是否HTTPS?}:::warning
D -->|是| E[TLS握手<br>协商加密参数]:::info
D -->|否| F[发送请求报文]:::primary
E --> F
F --> G[服务端处理<br>业务逻辑+数据库]:::warning
G --> H[接收响应头]:::info
H --> I[接收响应体<br>数据传输]:::info
I --> J{是否保持连接?}:::warning
J -->|是| K[连接复用<br>下次请求跳过B-E]:::primary
J -->|否| L[TCP四次挥手<br>关闭连接]:::error
classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
classDef error fill:#F44336,stroke:#D32F2F,color:#fff
classDef info fill:#2196F3,stroke:#1976D2,color:#fff
关键耗时环节:
| 阶段 | 典型耗时 | 优化空间 |
|---|---|---|
| DNS解析 | 20~200ms | DNS预解析、DNS缓存 |
| TCP握手 | 10~100ms | 连接复用(Keep-Alive) |
| TLS握手 | 50~200ms | TLS 1.3 Session复用 |
| 请求发送 | 1~10ms | 压缩请求体 |
| 服务端处理 | 50~5000ms | 后端优化、缓存 |
| 响应传输 | 10~5000ms | 响应压缩、CDN加速 |
| 数据解析 | 5~500ms | 高效解析、流式解析 |
2.2 Network Profiler的采集机制
Network Profiler通过Hook系统的网络库(@kit.NetworkKit中的http模块)来拦截所有HTTP请求。它记录的信息包括:
- 请求信息:URL、Method、Headers、请求体大小
- 响应信息:状态码、Headers、响应体大小
- 时间信息:开始时间、DNS耗时、连接耗时、首字节时间(TTFB)、总耗时
- 错误信息:超时、连接失败、证书错误等
2.3 Network Profiler面板布局
Network Profiler的面板分为三个区域:
- 时间线视图:顶部,展示所有请求的时间分布,横轴是时间,每个请求是一个色块
- 请求列表:中部,展示所有请求的详细信息,可按耗时/大小/类型排序
- 详情面板:底部,选中某个请求后展示其完整的请求/响应/耗时详情
三、代码实战
3.1 基础用法:HTTP请求追踪
import { http } from '@kit.NetworkKit';
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
interface ApiResponse<T> {
code: number;
message: string;
data: T;
}
interface UserInfo {
id: number;
name: string;
email: string;
avatar: string;
}
@Entry
@Component
struct NetworkProfilerDemo {
@State userInfo: UserInfo | null = null;
@State requestLog: string = '等待请求...';
@State isLoading: boolean = false;
build() {
Column({ space: 16 }) {
Text('Network Profiler 演示')
.fontSize(22)
.fontWeight(FontWeight.Bold)
Text(this.requestLog)
.fontSize(14)
.fontColor('#666666')
.textAlign(TextAlign.Center)
if (this.isLoading) {
LoadingProgress().width(48).height(48)
}
if (this.userInfo) {
this.UserInfoCard()
}
Button('发送GET请求')
.width('80%')
.onClick(() => this.sendGetRequest())
Button('发送POST请求')
.width('80%')
.onClick(() => this.sendPostRequest())
Button('模拟慢请求')
.width('80%')
.backgroundColor('#FF9800')
.onClick(() => this.sendSlowRequest())
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.padding(16)
}
// GET请求
private async sendGetRequest(): Promise<void> {
hiTraceMeter.startTrace('sendGetRequest', 1);
this.isLoading = true;
this.requestLog = '正在请求...';
try {
const httpRequest = http.createHttp();
const startTime = Date.now();
const response = await httpRequest.request(
'https://jsonplaceholder.typicode.com/users/1',
{
method: http.RequestMethod.GET,
header: { 'Content-Type': 'application/json' },
connectTimeout: 10000,
readTimeout: 10000
}
);
const elapsed = Date.now() - startTime;
if (response.responseCode === 200) {
this.userInfo = JSON.parse(response.result as string) as UserInfo;
this.requestLog = `GET请求成功,耗时: ${elapsed}ms`;
} else {
this.requestLog = `GET请求失败,状态码: ${response.responseCode}`;
}
httpRequest.destroy();
} catch (err) {
this.requestLog = `请求异常: ${JSON.stringify(err)}`;
} finally {
this.isLoading = false;
hiTraceMeter.finishTrace('sendGetRequest', 1);
}
}
// POST请求
private async sendPostRequest(): Promise<void> {
hiTraceMeter.startTrace('sendPostRequest', 2);
this.isLoading = true;
try {
const httpRequest = http.createHttp();
const requestBody = JSON.stringify({
title: 'HarmonyOS Network Test',
body: 'Testing Network Profiler',
userId: 1
});
const response = await httpRequest.request(
'https://jsonplaceholder.typicode.com/posts',
{
method: http.RequestMethod.POST,
header: { 'Content-Type': 'application/json' },
extraData: requestBody,
connectTimeout: 10000,
readTimeout: 10000
}
);
this.requestLog = `POST请求完成,状态码: ${response.responseCode}`;
httpRequest.destroy();
} catch (err) {
this.requestLog = `POST请求异常: ${JSON.stringify(err)}`;
} finally {
this.isLoading = false;
hiTraceMeter.finishTrace('sendPostRequest', 2);
}
}
// 模拟慢请求(大响应体)
private async sendSlowRequest(): Promise<void> {
hiTraceMeter.startTrace('sendSlowRequest', 3);
this.isLoading = true;
this.requestLog = '正在发送慢请求...';
try {
const httpRequest = http.createHttp();
const startTime = Date.now();
// 请求大量数据
const response = await httpRequest.request(
'https://jsonplaceholder.typicode.com/photos',
{
method: http.RequestMethod.GET,
connectTimeout: 30000,
readTimeout: 30000
}
);
const elapsed = Date.now() - startTime;
const dataSize = (response.result as string).length;
this.requestLog = `慢请求完成,耗时: ${elapsed}ms,数据量: ${(dataSize / 1024).toFixed(1)}KB`;
httpRequest.destroy();
} catch (err) {
this.requestLog = `慢请求异常: ${JSON.stringify(err)}`;
} finally {
this.isLoading = false;
hiTraceMeter.finishTrace('sendSlowRequest', 3);
}
}
@Builder
UserInfoCard() {
Column({ space: 8 }) {
Text(`用户: ${this.userInfo?.name}`)
.fontSize(18)
.fontWeight(FontWeight.Bold)
Text(`邮箱: ${this.userInfo?.email}`)
.fontSize(14)
.fontColor('#666666')
}
.width('90%')
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 4, color: '#1A000000', offsetY: 2 })
}
}
Network Profiler查看步骤:
- 打开Profiler面板,选择Network Profiler
- 点击"Record"开始采集
- 依次点击三个按钮发送请求
- 停止采集后,在请求列表中查看每个请求的详细信息
- 点击"模拟慢请求"的记录,你会看到响应体很大、传输耗时很长
3.2 进阶用法:请求耗时分析与数据传输统计
import { http } from '@kit.NetworkKit';
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
const TAG = 'NetworkAnalysis';
const DOMAIN = 0xFF00;
// 网络请求封装:自动记录耗时明细
class NetworkMonitor {
private static instance: NetworkMonitor | null = null;
private requestHistory: Map<string, {
url: string;
method: string;
startTime: number;
endTime: number;
responseSize: number;
statusCode: number;
error?: string;
}[]> = new Map();
static getInstance(): NetworkMonitor {
if (!NetworkMonitor.instance) {
NetworkMonitor.instance = new NetworkMonitor();
}
return NetworkMonitor.instance;
}
// 带监控的GET请求
async monitoredGet(url: string, tag: string = 'default'): Promise<http.HttpResponse> {
const requestId = `${tag}_${Date.now()}`;
hiTraceMeter.startTrace(`net_${requestId}`, requestId);
const httpRequest = http.createHttp();
const startTime = Date.now();
try {
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
connectTimeout: 10000,
readTimeout: 10000
});
const endTime = Date.now();
const responseSize = typeof response.result === 'string'
? response.result.length
: 0;
// 记录请求信息
this.recordRequest(tag, {
url,
method: 'GET',
startTime,
endTime,
responseSize,
statusCode: response.responseCode
});
hilog.info(DOMAIN, TAG,
`[${tag}] GET ${url} → ${response.responseCode} | ${endTime - startTime}ms | ${responseSize}B`
);
hiTraceMeter.finishTrace(`net_${requestId}`, requestId);
return response;
} catch (err) {
const endTime = Date.now();
this.recordRequest(tag, {
url,
method: 'GET',
startTime,
endTime,
responseSize: 0,
statusCode: -1,
error: JSON.stringify(err)
});
hiTraceMeter.finishTrace(`net_${requestId}`, requestId);
throw err;
} finally {
httpRequest.destroy();
}
}
// 记录请求
private recordRequest(tag: string, info: object): void {
if (!this.requestHistory.has(tag)) {
this.requestHistory.set(tag, []);
}
this.requestHistory.get(tag)!.push(info as any);
}
// 获取统计摘要
getSummary(tag: string): string {
const records = this.requestHistory.get(tag) || [];
if (records.length === 0) return '暂无请求记录';
const totalRequests = records.length;
const avgTime = records.reduce((sum, r) => sum + (r.endTime - r.startTime), 0) / totalRequests;
const totalSize = records.reduce((sum, r) => sum + r.responseSize, 0);
const errorCount = records.filter(r => r.error).length;
const maxTime = Math.max(...records.map(r => r.endTime - r.startTime));
return [
`请求总数: ${totalRequests}`,
`平均耗时: ${avgTime.toFixed(0)}ms`,
`最大耗时: ${maxTime}ms`,
`总数据量: ${(totalSize / 1024).toFixed(1)}KB`,
`错误数: ${errorCount}`
].join('\n');
}
}
@Entry
@Component
struct NetworkAnalysisDemo {
@State summaryText: string = '等待分析...';
@State isRunning: boolean = false;
private monitor: NetworkMonitor = NetworkMonitor.getInstance();
build() {
Column({ space: 16 }) {
Text('网络请求耗时分析')
.fontSize(22)
.fontWeight(FontWeight.Bold)
Text(this.summaryText)
.fontSize(14)
.fontColor('#333333')
.lineHeight(22)
.width('90%')
.padding(16)
.backgroundColor('#F5F5F5')
.borderRadius(8)
Button('并行发送多个请求')
.width('80%')
.onClick(() => this.sendParallelRequests())
Button('串行发送多个请求')
.width('80%')
.onClick(() => this.sendSequentialRequests())
Button('查看统计摘要')
.width('80%')
.backgroundColor('#FF9800')
.onClick(() => {
this.summaryText = this.monitor.getSummary('parallel') +
'\n---\n' + this.monitor.getSummary('sequential');
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
.padding(16)
}
// 并行请求
private async sendParallelRequests(): Promise<void> {
this.isRunning = true;
this.summaryText = '并行请求中...';
const urls = [
'https://jsonplaceholder.typicode.com/users/1',
'https://jsonplaceholder.typicode.com/users/2',
'https://jsonplaceholder.typicode.com/users/3',
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2'
];
const start = Date.now();
// 并行发送所有请求
await Promise.all(urls.map(url =>
this.monitor.monitoredGet(url, 'parallel')
));
const elapsed = Date.now() - start;
this.summaryText = `并行请求完成,总耗时: ${elapsed}ms`;
this.isRunning = false;
}
// 串行请求
private async sendSequentialRequests(): Promise<void> {
this.isRunning = true;
this.summaryText = '串行请求中...';
const urls = [
'https://jsonplaceholder.typicode.com/users/1',
'https://jsonplaceholder.typicode.com/users/2',
'https://jsonplaceholder.typicode.com/users/3',
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2'
];
const start = Date.now();
// 逐个发送请求
for (const url of urls) {
await this.monitor.monitoredGet(url, 'sequential');
}
const elapsed = Date.now() - start;
this.summaryText = `串行请求完成,总耗时: ${elapsed}ms`;
this.isRunning = false;
}
}
分析要点:
在Network Profiler中对比并行和串行请求的时间线视图,你会发现:
- 并行请求:5个请求同时发出,总耗时约等于最慢的那个请求
- 串行请求:5个请求依次发出,总耗时约等于5个请求耗时之和
这就是为什么实际开发中要尽量使用Promise.all并行请求的原因。
3.3 完整示例:网络异常检测与性能优化
import { http } from '@kit.NetworkKit';
import { hiTraceMeter } from '@kit.PerformanceAnalysisKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { connection } from '@kit.NetworkKit';
const TAG = 'NetworkOptimization';
const DOMAIN = 0xFF00;
// 优化的HTTP客户端:重试、超时、缓存
class OptimizedHttpClient {
private static instance: OptimizedHttpClient | null = null;
private cache: Map<string, { data: string; timestamp: number }> = new Map();
private readonly CACHE_TTL = 30000; // 缓存30秒
private readonly MAX_RETRIES = 2; // 最大重试次数
static getInstance(): OptimizedHttpClient {
if (!OptimizedHttpClient.instance) {
OptimizedHttpClient.instance = new OptimizedHttpClient();
}
return OptimizedHttpClient.instance;
}
// 带缓存的GET请求
async cachedGet(url: string): Promise<string> {
// 检查缓存
const cached = this.cache.get(url);
if (cached && Date.now() - cached.timestamp < this.CACHE_TTL) {
hilog.info(DOMAIN, TAG, `缓存命中: ${url}`);
return cached.data;
}
// 缓存未命中,发起请求
const data = await this.requestWithRetry(url);
// 更新缓存
this.cache.set(url, { data, timestamp: Date.now() });
return data;
}
// 带重试的请求
private async requestWithRetry(url: string): Promise<string> {
let lastError: Error | null = null;
for (let attempt = 0; attempt <= this.MAX_RETRIES; attempt++) {
try {
if (attempt > 0) {
// 重试前等待指数退避时间
const delay = Math.pow(2, attempt) * 500;
hilog.info(DOMAIN, TAG, `第${attempt}次重试,等待${delay}ms`);
await this.sleep(delay);
}
const httpRequest = http.createHttp();
const response = await httpRequest.request(url, {
method: http.RequestMethod.GET,
connectTimeout: 5000, // 连接超时5秒
readTimeout: 10000 // 读取超时10秒
});
httpRequest.destroy();
if (response.responseCode >= 200 && response.responseCode < 300) {
return response.result as string;
} else if (response.responseCode >= 500) {
// 服务端错误,可以重试
lastError = new Error(`服务端错误: ${response.responseCode}`);
hilog.warn(DOMAIN, TAG, `请求失败(${response.responseCode}),准备重试`);
} else {
// 客户端错误(4xx),不重试
throw new Error(`客户端错误: ${response.responseCode}`);
}
} catch (err) {
lastError = err as Error;
hilog.error(DOMAIN, TAG, `请求异常: ${JSON.stringify(err)}`);
}
}
throw lastError || new Error('请求失败');
}
// 检查网络状态
async checkNetworkStatus(): Promise<string> {
try {
const netHandle = connection.getDefaultNetSync();
const capabilities = netHandle.getConnectionProperties();
return `网络已连接,链路: ${JSON.stringify(capabilities)}`;
} catch {
return '网络未连接';
}
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
clearCache(): void {
this.cache.clear();
}
}
@Entry
@Component
struct NetworkOptimizationDemo {
@State logText: string = '等待操作...';
@State networkStatus: string = '检测中...';
private client: OptimizedHttpClient = OptimizedHttpClient.getInstance();
aboutToAppear(): void {
this.checkNetwork();
}
build() {
Column({ space: 12 }) {
Text('网络性能优化实战')
.fontSize(22)
.fontWeight(FontWeight.Bold)
Text(this.networkStatus)
.fontSize(12)
.fontColor('#999999')
Scroll() {
Text(this.logText)
.fontSize(13)
.fontColor('#333333')
.lineHeight(20)
.width('100%')
.padding(12)
.backgroundColor('#F5F5F5')
.borderRadius(8)
}
.layoutWeight(1)
.width('100%')
Row({ space: 12 }) {
Button('缓存请求')
.onClick(() => this.testCachedRequest())
Button('重试请求')
.backgroundColor('#FF9800')
.onClick(() => this.testRetryRequest())
Button('清理缓存')
.backgroundColor('#9C27B0')
.onClick(() => {
this.client.clearCache();
this.addLog('缓存已清理');
})
}
}
.width('100%')
.height('100%')
.padding(16)
}
private async checkNetwork(): Promise<void> {
this.networkStatus = await this.client.checkNetworkStatus();
}
// 测试缓存请求
private async testCachedRequest(): Promise<void> {
hiTraceMeter.startTrace('cachedRequest', 1);
const url = 'https://jsonplaceholder.typicode.com/users/1';
// 第一次请求:缓存未命中
const start1 = Date.now();
await this.client.cachedGet(url);
const time1 = Date.now() - start1;
this.addLog(`首次请求: ${time1}ms(缓存未命中)`);
// 第二次请求:缓存命中
const start2 = Date.now();
await this.client.cachedGet(url);
const time2 = Date.now() - start2;
this.addLog(`二次请求: ${time2}ms(缓存命中)`);
this.addLog(`性能提升: ${((time1 - time2) / time1 * 100).toFixed(1)}%`);
hiTraceMeter.finishTrace('cachedRequest', 1);
}
// 测试重试请求
private async testRetryRequest(): Promise<void> {
hiTraceMeter.startTrace('retryRequest', 2);
try {
// 使用一个可能失败的URL测试重试逻辑
const data = await this.client.cachedGet('https://httpbin.org/status/500');
this.addLog('请求成功(意外)');
} catch (err) {
this.addLog(`重试后仍然失败: ${JSON.stringify(err)}`);
}
hiTraceMeter.finishTrace('retryRequest', 2);
}
private addLog(msg: string): void {
const time = new Date().toLocaleTimeString();
this.logText = `[${time}] ${msg}\n${this.logText}`;
}
}
Network Profiler中的观察:
- 开启Network Profiler后点击"缓存请求"
- 第一次请求会在时间线上显示一个完整的HTTP色块
- 第二次请求几乎看不到色块——因为直接从内存缓存返回,没有网络IO
- 点击"重试请求",你会看到多个请求色块——这就是重试机制在Profiler中的可视化表现
四、踩坑与注意事项
坑点1:HTTPS请求显示为加密数据
在HarmonyOS 5.0中,Network Profiler对HTTPS请求只能看到连接信息,请求体和响应体都是加密的,看不到具体内容。
解决方案:HarmonyOS 6.0支持HTTPS解密功能,需要在设备设置中安装调试证书。安装后,Profiler可以自动解密HTTPS流量,查看明文请求/响应。
坑点2:WebSocket请求不显示
Network Profiler默认只追踪HTTP/HTTPS请求,WebSocket连接不会出现在请求列表中。
变通方法:对于WebSocket的调试,建议在代码层面添加日志,记录每条消息的发送和接收时间。或者使用hiTraceMeter标记WebSocket的关键操作。
坑点3:请求列表中看不到http.createHttp()的创建时机
Network Profiler记录的是request()调用的时机,而不是createHttp()的时机。如果你在页面初始化时就创建了http对象但延迟调用request,Profiler中显示的开始时间会晚于你的预期。
建议:不要过早创建http对象,在真正需要发请求时再创建。或者使用hiTraceMeter标记创建时机,和Profiler数据对照分析。
坑点4:并发请求过多导致连接池耗尽
虽然并行请求比串行请求快,但如果同时发出几十个请求,系统TCP连接池可能不够用,导致请求排队等待,反而更慢。
最佳实践:控制并发数在6~8个以内。可以使用一个简单的并发控制器:
class ConcurrencyController {
private running: number = 0;
private queue: (() => Promise<void>)[] = [];
private readonly maxConcurrency: number;
constructor(maxConcurrency: number = 6) {
this.maxConcurrency = maxConcurrency;
}
async run<T>(task: () => Promise<T>): Promise<T> {
return new Promise((resolve, reject) => {
const execute = async () => {
this.running++;
try {
const result = await task();
resolve(result);
} catch (err) {
reject(err);
} finally {
this.running--;
this.next();
}
};
if (this.running < this.maxConcurrency) {
execute();
} else {
this.queue.push(execute);
}
});
}
private next(): void {
if (this.queue.length > 0 && this.running < this.maxConcurrency) {
const task = this.queue.shift();
task?.();
}
}
}
坑点5:DNS解析耗时被忽略
很多人只关注请求的总耗时,忽略了DNS解析的时间。在某些网络环境下(比如首次访问某个域名),DNS解析可能要花几百毫秒甚至几秒。
优化方案:在应用启动时预解析常用域名。HarmonyOS目前没有直接的DNS预解析API,但可以通过提前发送一个HEAD请求来触发DNS缓存。
坑点6:大响应体导致内存飙升
如果接口返回了大量数据(比如一个10MB的JSON),response.result会把整个响应体加载到内存中,可能导致内存飙升甚至OOM。
解决方案:后端应该支持分页和字段过滤,前端只请求需要的数据。如果必须处理大响应,考虑使用流式解析(SAX风格的JSON解析器)。
坑点7:Network Profiler影响请求耗时
Profiler本身会增加少量网络请求的耗时(通常<5%),因为它需要拦截和记录数据。如果Profiler显示的耗时和实际体感差异很大,可能是Profiler的额外开销导致的。
建议:性能基准测试应该在关闭Profiler的情况下进行。Profiler用于定位问题,不用于精确测量。
五、HarmonyOS 6适配说明
API差异
| API | HarmonyOS 5.0 | HarmonyOS 6.0 | 迁移建议 |
|---|---|---|---|
| HTTPS解密 | 不支持 | 支持调试证书解密 | 安装调试证书后可查看HTTPS明文 |
| WebSocket追踪 | 不支持 | 支持WebSocket帧级别追踪 | 利用新能力分析实时通信性能 |
| 请求时间拆分 | 仅总耗时 | 拆分DNS/TCP/TLS/TTFB/传输 | 根据拆分数据精准定位瓶颈环节 |
| 流量统计 | 按请求统计 | 新增按域名/时间维度聚合 | 使用聚合视图发现流量异常 |
| 网络质量检测 | 无 | 新增网络质量评估API | 根据网络质量动态调整请求策略 |
| 请求对比 | 无 | 新增请求对比功能 | 对比优化前后的请求耗时 |
行为变更
- 默认采集范围扩大:6.0默认采集所有网络请求(包括框架内部的请求),5.0只采集业务代码发起的请求
- 时间精度提升:6.0的请求耗时精度从毫秒级提升到微秒级,更适合分析快速请求
- 自动异常检测:6.0会自动标记异常请求(超时、4xx/5xx、重复请求),在请求列表中用红色高亮
适配代码
// HarmonyOS 6.0 新增的网络质量检测API
import { connection } from '@kit.NetworkKit';
class NetworkQualityMonitor {
// 6.0新增:获取网络质量评分
async getNetworkQuality(): Promise<string> {
try {
const netHandle = connection.getDefaultNetSync();
// 6.0新增方法
const quality = await netHandle.getNetQuality();
switch (quality) {
case connection.NetQuality.EXCELLENT:
return '网络质量:优秀 → 可加载高清资源';
case connection.NetQuality.GOOD:
return '网络质量:良好 → 正常加载';
case connection.NetQuality.MODERATE:
return '网络质量:一般 → 建议压缩资源';
case connection.NetQuality.POOR:
return '网络质量:差 → 仅加载必要数据';
default:
return '网络质量:未知';
}
} catch {
return '网络不可用';
}
}
// 根据网络质量调整请求策略
getRequestStrategy(): { timeout: number; compression: boolean; prefetch: boolean } {
// 实际实现中应调用getNetworkQuality()获取质量评分
return {
timeout: 10000,
compression: true,
prefetch: false
};
}
}
六、总结
| 维度 | 评价 |
|---|---|
| 学习难度 | ⭐⭐⭐ |
| 使用频率 | ⭐⭐⭐⭐ |
| 重要程度 | ⭐⭐⭐⭐ |
网络性能优化有个特点:它不完全在你的控制范围内——服务端慢你管不了,用户网络差你也管不了。但你能做的是:在自己的控制范围内做到最好。
具体来说就是三件事:
- 减少不必要的请求:能用缓存的就别重复请求,能合并的接口就别分开调
- 减少每次请求的数据量:请求参数精简、响应字段过滤、数据压缩
- 优雅处理网络异常:超时重试、降级策略、离线缓存
Network Profiler帮你发现"慢在哪",但"怎么快起来"还需要你对业务逻辑的理解。工具只是手段,优化才是目的。
下一篇我们将进入Render Profiler,看看如何让UI渲染丝般顺滑。
- 点赞
- 收藏
- 关注作者
评论(0)