Skip to content

内存优化

鸿蒙内存管理:内存泄漏检测、GC 优化、大对象处理、图片内存控制。


1. 内存模型

1.1 内存分布

应用内存分布
├─ 堆内存(Heap)
│   ├─ 对象实例
│   ├─ 数组
│   └─ 大对象(图片、视频)
├─ 栈内存(Stack)
│   ├─ 局部变量
│   └─ 函数调用栈
└─ 原生内存(Native)
    ├─ C++ 对象
    └─ 图形缓冲区

1.2 内存限制

设备类型内存限制警告阈值
低端机(2-4GB)256MB200MB
中端机(4-8GB)512MB400MB
高端机(8GB+)1GB800MB

2. 内存泄漏检测

2.1 常见泄漏场景

typescript
// ❌ 错误:闭包引用导致泄漏
class BadComponent {
    private timer: number | null = null
    private data: any = null

    start() {
        this.timer = setInterval(() => {
            // 闭包引用了 this,导致组件无法释放
            this.data = loadData()
        }, 1000)
    }

    // 忘记清理定时器
    // aboutToDisappear() 中未清除
}

// ✅ 正确:及时清理
class GoodComponent {
    private timer: number | null = null
    private data: any = null

    start() {
        this.timer = setInterval(() => {
            this.data = loadData()
        }, 1000)
    }

    aboutToDisappear() {
        // 清理定时器
        if (this.timer) {
            clearInterval(this.timer)
            this.timer = null
        }
        // 释放大对象
        this.data = null
    }
}

2.2 事件监听泄漏

typescript
// ❌ 错误:未移除事件监听
class BadComponent {
    aboutToAppear() {
        eventHub.on('customEvent', this.handleEvent.bind(this))
        // 组件销毁后监听仍存在
    }
}

// ✅ 正确:成对注册/移除
class GoodComponent {
    private handler: (e: any) => void = (e) => this.handleEvent(e)

    aboutToAppear() {
        eventHub.on('customEvent', this.handler)
    }

    aboutToDisappear() {
        eventHub.off('customEvent', this.handler)
    }
}

3. 图片内存优化

3.1 图片缩放

typescript
// ❌ 错误:加载原图(可能 10MB+)
Image($r('app.media.large_image'))
    .width(100)
    .height(100)
// 虽然显示 100x100,但内存中是原图大小

// ✅ 正确:使用缩略图
Image($r('app.media.large_image_thumbnail'))
    .width(100)
    .height(100)
// 缩略图只有 50KB,内存占用小 200 倍

3.2 图片缓存

typescript
class ImageCache {
    private cache: LruCache<string, imagePixel.ImagePixel> = new LruCache(50)

    // 获取缓存图片
    get(url: string): imagePixel.ImagePixel | null {
        return this.cache.get(url) || null
    }

    // 设置缓存
    put(url: string, pixel: imagePixel.ImagePixel): void {
        this.cache.put(url, pixel)
    }

    // 清理缓存
    clear(): void {
        this.cache.clear()
    }
}

4. GC 优化

4.1 减少 GC 压力

typescript
// ❌ 错误:频繁创建对象
function badLoop() {
    for (let i = 0; i < 10000; i++) {
        let obj = { id: i, name: `item_${i}` }  // 每次循环创建新对象
        process(obj)
    }
}

// ✅ 正确:复用对象
function goodLoop() {
    let obj = { id: 0, name: '' }
    for (let i = 0; i < 10000; i++) {
        obj.id = i
        obj.name = `item_${i}`  // 复用同一对象
        process(obj)
    }
}

4.2 大对象处理

typescript
// ❌ 错误:大对象长期持有
class BadClass {
    private largeData: ArrayBuffer | null = null

    loadData() {
        this.largeData = new ArrayBuffer(100 * 1024 * 1024)  // 100MB
        // 用完不释放
    }
}

// ✅ 正确:用完即释放
class GoodClass {
    private largeData: ArrayBuffer | null = null

    async loadData() {
        this.largeData = new ArrayBuffer(100 * 1024 * 1024)
        
        try {
            // 使用数据
            await process(this.largeData)
        } finally {
            // 用完释放
            this.largeData = null
        }
    }
}

5. 内存监控

5.1 内存使用监控

typescript
import { systemMemoryInfo } from '@kit.SystemKit'

// 获取内存信息
let memInfo = systemMemoryInfo.getMemoryInfo()
console.log('总内存:', memInfo.totalMemory)
console.log('可用内存:', memInfo.availableMemory)
console.log('已用内存:', memInfo.usedMemory)

// 内存警告监听
systemMemoryInfo.on('memoryWarning', (level: number) => {
    if (level === systemMemoryInfo.MemoryLevel.CRITICAL) {
        // 紧急清理缓存
        this.clearCache()
    }
})

6. 面试高频考点

Q1: 内存泄漏常见原因?

回答:定时器未清理、事件监听未移除、闭包引用、大对象长期持有、单例持有 Activity 引用。

Q2: 图片内存如何优化?

回答:使用缩略图而非原图、指定宽高、LruCache 缓存、及时释放。


🐱 小猫提示:内存优化记住 "定时器清理、监听移除、缩略图、LruCache、大对象及时释放"