Harmony学习之性能优化实战
Harmony学习之性能优化实战
一、场景引入
小明开发的新闻阅读应用在测试时发现以下问题:应用启动慢、列表滑动卡顿、内存占用高。用户反馈应用体验不佳,急需进行性能优化。HarmonyOS提供了丰富的性能优化工具和方法,帮助开发者提升应用质量。
二、核心优化维度
1. 性能指标定义
HarmonyOS应用性能主要关注以下指标:
| 指标 | 标准值 | 测量工具 |
|---|---|---|
| 应用启动时间 | < 800ms | HiTraceMeter |
| 界面刷新率 | ≥ 60fps | 性能监视器 |
| 内存占用 | < 200MB | 内存分析工具 |
| 电量消耗 | < 5%/h | 电量分析工具 |
| 包体大小 | < 20MB | 构建分析 |
三、关键优化技术
1. 启动优化实践
优化首页加载速度:
// entry/src/main/ets/pages/HomePage.ets
@Component
struct HomePage {
@State newsList: NewsItem[] = [];
@State loaded: boolean = false;
private lazyLoadTask: number | null = null;
aboutToAppear() {
// 延迟加载非关键资源
this.lazyLoadTask = setTimeout(() => {
this.loadInitialData();
}, 100);
}
aboutToDisappear() {
if (this.lazyLoadTask) {
clearTimeout(this.lazyLoadTask);
}
}
async loadInitialData() {
// 1. 优先加载可见区域数据
const initialData = await this.loadFirstScreenData();
this.newsList = initialData;
this.loaded = true;
// 2. 延迟加载剩余数据
setTimeout(() => {
this.loadRemainingData();
}, 300);
}
async loadFirstScreenData(): Promise<NewsItem[]> {
// 只加载前5条,保证首屏快速显示
return await NewsService.getNews(0, 5);
}
async loadRemainingData() {
const moreData = await NewsService.getNews(5, 20);
this.newsList = [...this.newsList, ...moreData];
}
build() {
Column() {
if (!this.loaded) {
// 骨架屏占位
this.buildSkeleton();
} else {
this.buildContent();
}
}
}
@Builder
buildSkeleton() {
Column() {
ForEach([1, 2, 3, 4, 5], (index) => {
Row() {
Column() {
Row()
.width('100%')
.height(20)
.backgroundColor('#F0F0F0')
.margin({ bottom: 8 })
Row()
.width('60%')
.height(15)
.backgroundColor('#F0F0F0')
}
.layoutWeight(1)
.margin({ right: 10 })
Row()
.width(80)
.height(60)
.backgroundColor('#F0F0F0')
}
.padding(10)
.margin({ bottom: 10 })
})
}
}
}
2. 列表渲染优化
优化长列表性能:
// entry/src/main/ets/components/OptimizedList.ets
@Component
struct OptimizedList {
@Prop newsList: NewsItem[] = [];
private itemHeights: Map<number, number> = new Map();
// 使用缓存避免重复计算
getItemHeight(index: number): number {
if (this.itemHeights.has(index)) {
return this.itemHeights.get(index)!;
}
const item = this.newsList[index];
const height = this.calculateHeight(item);
this.itemHeights.set(index, height);
return height;
}
// 简化高度计算逻辑
private calculateHeight(item: NewsItem): number {
const titleLines = Math.ceil(item.title.length / 30);
const summaryLines = Math.ceil(item.summary.length / 50);
return 20 + (titleLines + summaryLines) * 20 + 60;
}
// 优化ItemBuilder
@Builder
buildListItem(item: NewsItem, index: number) {
ListItem() {
Row() {
// 使用LazyForEach加载图片
if (item.imageUrl) {
LazyImage({ uri: item.imageUrl })
.width(80)
.height(60)
.borderRadius(5)
.margin({ right: 10 })
}
Column() {
Text(item.title)
.fontSize(16)
.maxLines(2)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.margin({ bottom: 5 })
Text(item.summary)
.fontSize(14)
.maxLines(3)
.textOverflow({ overflow: TextOverflow.Ellipsis })
.fontColor(Color.Gray)
}
.layoutWeight(1)
}
.padding(10)
}
.height(this.getItemHeight(index)) // 设置固定高度提升性能
}
build() {
List({ space: 5 }) {
LazyForEach(this.newsList, (item: NewsItem, index: number) => {
this.buildListItem(item, index);
})
}
.cachedCount(5) // 缓存5个屏幕外的Item
.listDirection(Axis.Vertical)
}
}
// 懒加载图片组件
@Component
struct LazyImage {
@Prop uri: string = '';
@State loaded: boolean = false;
@State showPlaceholder: boolean = true;
private loadingTask: number | null = null;
aboutToAppear() {
this.startLazyLoad();
}
aboutToDisappear() {
this.cancelLoading();
}
startLazyLoad() {
// 延迟加载图片
this.loadingTask = setTimeout(() => {
this.loadImage();
}, 200);
}
async loadImage() {
if (!this.uri) {
this.showPlaceholder = false;
return;
}
try {
// 实际项目中应该使用图片加载库
this.loaded = true;
this.showPlaceholder = false;
} catch (error) {
console.error('图片加载失败:', error);
}
}
cancelLoading() {
if (this.loadingTask) {
clearTimeout(this.loadingTask);
}
}
build() {
Stack() {
if (this.showPlaceholder) {
// 占位图
Row()
.width('100%')
.height('100%')
.backgroundColor('#F0F0F0')
}
if (this.loaded) {
// 实际图片
Image(this.uri)
.width('100%')
.height('100%')
.objectFit(ImageFit.Cover)
}
}
}
}
3. 内存优化策略
优化图片内存使用:
// entry/src/main/ets/utils/MemoryOptimizer.ets
import image from '@ohos.multimedia.image';
export class MemoryOptimizer {
// 压缩图片到合适尺寸
static async compressImage(
pixelMap: image.PixelMap,
maxWidth: number = 800,
maxHeight: number = 600
): Promise<image.PixelMap> {
const scale = Math.min(maxWidth / pixelMap.width, maxHeight / pixelMap.height);
if (scale >= 1) {
return pixelMap; // 不需要压缩
}
const operations: image.ImageOperation[] = [{
operationType: image.OperationType.SCALE,
scaleOptions: {
scaleX: scale,
scaleY: scale
}
}];
return await image.applyOperations(pixelMap, operations);
}
// 清理图片缓存
static clearImageCache(cache: Map<string, any>): void {
const now = Date.now();
const maxAge = 5 * 60 * 1000; // 5分钟
for (const [key, value] of cache.entries()) {
if (now - value.timestamp > maxAge) {
cache.delete(key);
if (value.pixelMap && value.pixelMap.release) {
value.pixelMap.release();
}
}
}
}
}
4. 网络请求优化
// entry/src/main/ets/utils/NetworkOptimizer.ets
import http from '@ohos.net.http';
export class NetworkOptimizer {
private static cache = new Map<string, { data: any, timestamp: number }>();
private static pendingRequests = new Map<string, Promise<any>>();
// 带缓存的网络请求
static async requestWithCache(
url: string,
options?: http.HttpRequestOptions,
cacheTime: number = 300000 // 5分钟缓存
): Promise<any> {
const cacheKey = `${url}_${JSON.stringify(options)}`;
// 检查缓存
const cached = this.cache.get(cacheKey);
if (cached && (Date.now() - cached.timestamp) < cacheTime) {
return cached.data;
}
// 检查是否有相同请求正在进行
if (this.pendingRequests.has(cacheKey)) {
return await this.pendingRequests.get(cacheKey)!;
}
// 发起新请求
const requestPromise = this.makeRequest(url, options);
this.pendingRequests.set(cacheKey, requestPromise);
try {
const data = await requestPromise;
// 缓存结果
this.cache.set(cacheKey, {
data,
timestamp: Date.now()
});
return data;
} finally {
this.pendingRequests.delete(cacheKey);
}
}
private static async makeRequest(
url: string,
options?: http.HttpRequestOptions
): Promise<any> {
const httpRequest = http.createHttp();
try {
const response = await httpRequest.request(url, {
method: options?.method || http.RequestMethod.GET,
readTimeout: 10000, // 10秒超时
connectTimeout: 5000, // 5秒连接超时
...options
});
if (response.responseCode === 200) {
return JSON.parse(response.result.toString());
} else {
throw new Error(`请求失败: ${response.responseCode}`);
}
} finally {
httpRequest.destroy();
}
}
}
四、实战案例:优化新闻阅读应用
1. 性能监控组件
// entry/src/main/ets/components/PerformanceMonitor.ets
@Component
struct PerformanceMonitor {
@State fps: number = 0;
@State memory: number = 0;
@State cpu: number = 0;
private frameCount: number = 0;
private lastTime: number = 0;
private monitorTask: number | null = null;
aboutToAppear() {
this.startMonitoring();
}
aboutToDisappear() {
this.stopMonitoring();
}
startMonitoring() {
this.lastTime = Date.now();
this.monitorTask = setInterval(() => {
this.updateMetrics();
}, 1000);
}
updateMetrics() {
// 计算FPS
const now = Date.now();
const elapsed = now - this.lastTime;
this.fps = Math.round((this.frameCount * 1000) / elapsed);
this.frameCount = 0;
this.lastTime = now;
// 获取内存和CPU信息
this.updateSystemMetrics();
}
async updateSystemMetrics() {
try {
const systemMetrics = await this.getSystemMetrics();
this.memory = systemMetrics.memory;
this.cpu = systemMetrics.cpu;
} catch (error) {
console.error('获取系统指标失败:', error);
}
}
onFrame() {
this.frameCount++;
}
stopMonitoring() {
if (this.monitorTask) {
clearInterval(this.monitorTask);
}
}
build() {
Column() {
Row() {
Text(`FPS: ${this.fps}`)
.fontSize(12)
.fontColor(this.fps < 50 ? Color.Red : Color.Green)
Text(`内存: ${this.memory.toFixed(1)}MB`)
.fontSize(12)
.margin({ left: 20 })
Text(`CPU: ${this.cpu.toFixed(1)}%`)
.fontSize(12)
.margin({ left: 20 })
}
.padding(5)
.backgroundColor(Color.Black)
}
}
}
五、最佳实践
1. 代码分割与懒加载
// module.json5
{
"module": {
"name": "entry",
"type": "entry",
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages.json",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"launchType": "standard"
},
{
"name": "DetailAbility",
"srcEntry": "./ets/detailability/DetailAbility.ets",
"launchType": "standard",
"visible": false
}
],
"extensionAbilities": [
{
"name": "ServiceExtAbility",
"srcEntry": "./ets/serviceextability/ServiceExtAbility.ets",
"type": "service"
}
]
}
}
2. 图片资源优化
- 使用WebP格式替代PNG/JPG
- 实现图片懒加载
- 使用合适的图片尺寸
- 实现渐进式加载
六、总结
性能优化是一个持续的过程,需要在实际开发中不断监控和优化。建议:
- 监控先行:在开发阶段就集成性能监控
- 渐进优化:从影响最大的问题开始优化
- 定期检查:定期使用性能分析工具检查应用
- 用户反馈:关注用户反馈的性能问题
通过合理的优化策略,可以显著提升应用性能和用户体验。

浙公网安备 33010602011771号