Skip to content

缓存机制

鸿蒙缓存:内存缓存、KV-Store 缓存、图片缓存、LruCache。


1. 缓存层级

用户请求数据


┌─ 内存缓存(最快,LruCache)─────┐
│ 命中 → 直接返回                    │
│ 未命中 →                         │
│   ↓                               │
├─ KV-Store 缓存(中速)───────────┐
│ 命中 → 返回                       │
│ 未命中 →                         │
│   ↓                               │
├─ 本地文件缓存(较慢)─────────────┐
│ 命中 → 返回                       │
│ 未命中 →                         │
│   ↓                               │
└─ 网络请求(最慢)                  │

返回数据                              │
    │                                 │
    ▼                                 ▼
存入各级缓存(回填)

2. LruCache 内存缓存

2.1 实现 LRU 缓存

typescript
class LruCache<K, V> {
    private maxSize: number
    private cache: Map<K, V>

    constructor(maxSize: number = 100) {
        this.maxSize = maxSize
        this.cache = new Map()
    }

    // 获取缓存
    get(key: K): V | undefined {
        let value = this.cache.get(key)
        if (value !== undefined) {
            // 更新访问顺序(移到最新)
            this.cache.delete(key)
            this.cache.set(key, value)
        }
        return value
    }

    // 设置缓存
    put(key: K, value: V): void {
        if (this.cache.size >= this.maxSize) {
            // 删除最久未使用的(Map 第一个)
            let firstKey = this.cache.keys().next().value
            this.cache.delete(firstKey)
        }
        this.cache.set(key, value)
    }

    // 删除缓存
    remove(key: K): void {
        this.cache.delete(key)
    }

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

    // 获取大小
    size(): number {
        return this.cache.size
    }
}

2.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)
    }

    // 加载图片(先查缓存,再下载)
    async load(url: string): Promise<imagePixel.ImagePixel> {
        let cached = this.get(url)
        if (cached) {
            console.log('缓存命中:', url)
            return cached
        }

        // 缓存未命中,下载
        let pixel = await this.downloadImage(url)
        this.put(url, pixel)
        return pixel
    }

    private async downloadImage(url: string): Promise<imagePixel.ImagePixel> {
        let httpClient = http.createHttp()
        let response = await httpClient.request(url, {
            method: http.HttpRequestMethod.GET
        })
        httpClient.destroy()
        // 图片解码...
        return pixel
    }
}

3. 缓存策略

3.1 缓存过期策略

typescript
interface CacheEntry<V> {
    data: V
    timestamp: number
    ttl: number  // 生存时间(毫秒)
}

class TimeCache<V> {
    private cache: Map<string, CacheEntry<V>> = new Map()

    get(key: string): V | null {
        let entry = this.cache.get(key)
        if (!entry) return null

        // 检查是否过期
        if (Date.now() - entry.timestamp > entry.ttl) {
            this.cache.delete(key)
            return null
        }

        return entry.data
    }

    put(key: string, data: V, ttl: number = 3600000): void {
        this.cache.set(key, {
            data: data,
            timestamp: Date.now(),
            ttl: ttl
        })
    }

    // 清理过期条目
    cleanup(): void {
        let now = Date.now()
        for (let [key, entry] of this.cache.entries()) {
            if (now - entry.timestamp > entry.ttl) {
                this.cache.delete(key)
            }
        }
    }
}

3.2 缓存方案对比

方案速度容量持久化适用场景
内存缓存⚡⚡⚡频繁访问数据
KV-Store 缓存⚡⚡应用重启后恢复
文件缓存图片/大文件
AssetStore✅ 卸载保留敏感数据

4. 面试高频考点

Q1: 鸿蒙推荐哪些缓存策略?

回答:内存(LruCache)→ KV-Store → 文件 → 网络。多级缓存,最近最常使用优先。

Q2: 图片缓存如何实现?

回答:先查 LruCache 内存缓存,命中直接返回;未命中下载图片,解码后存入缓存并返回。


🐱 小猫提示:缓存机制记住 "LruCache 内存、多级缓存、TTL 过期、图片先查缓存再下载"