Skip to content

diwand/imageLoader

Repository files navigation

image_loader

一款用于 HarmonyOS 应用的图片加载与缓存三方库,提供网络图片下载、本地图片解码、视频封面提取、内存缓存、磁盘缓存、并发控制和自定义缓存 Key 等能力。

功能特性

  • 支持 http / https 网络图片加载。
  • 支持 rawfile 图片、本地文件图片加载。
  • 支持本地视频封面加载。
  • 支持 gif / webp 动图加载。
  • 支持内存缓存和磁盘缓存。
  • 支持自定义缓存目录、缓存大小和缓存数量。
  • 支持按任务类型拆分网络并发和本地解码并发。
  • 支持自定义缓存 Key,适配业务侧稳定资源 ID。
  • 支持占位图、预加载、取消单个请求、清除缓存和查询缓存大小。

下载安装

发布到 ohpm 后,可通过包管理器安装:

ohpm install @qinbaobao/image_loader

本仓库 demo 使用本地模块依赖:

{
  "dependencies": {
    "@qinbaobao/image_loader": "file:../imageLoader"
  }
}

权限配置

如果需要加载网络图片,请在应用模块的 module.json5 中声明网络权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

初始化

建议在 UIAbility.onCreate 中初始化一次。该库作为应用级图片缓存管理器使用,只依赖 UIAbilityContext,不依赖窗口对象,通常不需要重复初始化。

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'
import { window } from '@kit.ArkUI'
import { ImageLoader } from '@qinbaobao/image_loader'

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    ImageLoader.getInstance().initImageLoader({
      context: this.context,
      maxRunningCount: 10,
      maxNetworkRunningCount: 6,
      maxLocalRunningCount: 4,
      debug: true
    })
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    windowStage.loadContent('pages/Index')
  }
}

加载图片

ImageLoader 通过 Request 发起图片加载,加载成功后回调 PixelMap 或动图 base64 字符串,调用方再交给系统 Image 组件渲染。

import { common } from '@kit.AbilityKit'
import { image } from '@kit.ImageKit'
import { ImageLoader, Request, RequestState } from '@qinbaobao/image_loader'

@Component
struct NetworkImageView {
  @State bitmap: image.PixelMap | string | Resource | undefined = undefined
  private request?: Request
  private version: number = 0

  aboutToAppear(): void {
    this.loadImage()
  }

  aboutToDisappear(): void {
    this.cancelImage()
  }

  private loadImage(): void {
    this.version++
    const currentVersion = this.version

    this.request = {
      url: 'https://example.com/image.jpg',
      uniqueID: 'image-id-001',
      imageFit: ImageFit.Cover,
      width: 160,
      height: 120,
      context: getContext(this) as common.UIAbilityContext,
      imageVerion: currentVersion,
      state: RequestState.NONE,
      onLoad: (requestVersion: number, bitmap?: image.PixelMap | string) => {
        if (requestVersion !== this.version) {
          return
        }
        this.bitmap = bitmap
      }
    }

    ImageLoader.getInstance().addRequest(this.request)
  }

  private cancelImage(): void {
    if (this.request) {
      ImageLoader.getInstance().cancel(this.request)
      this.request.state = RequestState.DESTROY
      this.request = undefined
    }
    this.bitmap = undefined
    this.version++
  }

  build() {
    Image(this.bitmap)
      .width(160)
      .height(120)
      .objectFit(ImageFit.Cover)
  }
}

预加载

预加载使用同一个 Request 结构。预加载结果会进入缓存,后续相同缓存 Key 的请求可直接复用缓存。

ImageLoader.getInstance().preload({
  url: 'https://example.com/image.jpg',
  uniqueID: 'image-id-001',
  imageFit: ImageFit.Cover,
  width: 160,
  height: 120,
  context: getContext(this) as common.UIAbilityContext,
  imageVerion: 1,
  state: RequestState.NONE
})

缓存管理

查询缓存大小

const size = await ImageLoader.getInstance().getCacheSize(getContext(this) as common.UIAbilityContext)

清除缓存

const success = await ImageLoader.getInstance().clearCache(getContext(this) as common.UIAbilityContext)

clearCache 会同时清理内存缓存和磁盘缓存。

自定义缓存 Key

默认缓存 Key 使用 uniqueID ?? url。如果同一张图片的 URL 会变化,但业务 ID 稳定,建议传入 uniqueID,避免重复下载。

this.request = {
  url: `${imageUrl}?t=${Date.now()}`,
  uniqueID: imageId,
  imageFit: ImageFit.Cover,
  width: 160,
  height: 120,
  context: getContext(this) as common.UIAbilityContext,
  imageVerion: 1,
  state: RequestState.NONE,
  onLoad: (_version, bitmap) => {
    this.bitmap = bitmap
  }
}

也可以实现 IImageLoadKey 完全接管缓存路径和内存缓存 Key 的生成:

import fs from '@ohos.file.fs'
import { IImageLoadKey, ImageParam } from '@qinbaobao/image_loader'

@Sendable
class CustomImageKey implements IImageLoadKey {
  private getCacheDir(context: Context): string {
    const dir = `${context.cacheDir}/image_cache`
    if (!fs.accessSync(dir)) {
      fs.mkdirSync(dir, true)
    }
    return dir
  }

  getCachePath(param: ImageParam): string {
    const id = encodeURIComponent(param.uniqueID ?? param.url)
    return `${this.getCacheDir(param.context)}/${id}_${param.width}_${param.height}_${param.crop ?? false}`
  }

  getDownloadPath(param: ImageParam): string {
    const id = encodeURIComponent(param.uniqueID ?? param.url)
    return `${this.getCacheDir(param.context)}/${id}`
  }

  getBitmapMemoryKey(param: ImageParam): string {
    return `${param.uniqueID ?? param.url}_${param.width}_${param.height}_${param.crop ?? false}`
  }
}

ImageLoader.getInstance().initImageLoader({
  context: this.context,
  imageKey: new CustomImageKey()
})

配置说明

ImageLoadConfig 支持以下配置:

参数 类型 默认值 说明
context Context 必填 应用上下文。
maxFileSize number 1GB 磁盘缓存大小,单位 byte。
maxCacheSize number 256MB 内存缓存大小,单位 byte。
maxCacheCount number 500 内存缓存条目数量。
maxRunningCount number 10 图片任务总并发数。
maxNetworkRunningCount number 跟随 maxRunningCount 网络下载任务并发数。
maxLocalRunningCount number 跟随 maxRunningCount 本地缓存读取、文件读取、图片解码等非网络任务并发数。
connectTimeout number 60000 网络连接超时时间,单位 ms。
readTimeout number 60000 网络读取超时时间,单位 ms。
cacheFolder string imageloader 磁盘缓存目录名,位于 context.cacheDir 下。
debug boolean false 是否开启调试日志。
imageKey IImageLoadKey DefaultImageKey 自定义缓存 Key 生成器。
LIFO boolean false 等待队列是否后进先出。

为避免配置过高导致 CPU、内存、taskpool 或 IO 压力过大,库内部对部分配置做了硬上限保护:

常量 默认值
MAX_RUNNING_COUNT 16
MAX_NETWORK_RUNNING_COUNT 12
MAX_LOCAL_RUNNING_COUNT 6
MAX_MEMORY_CACHE_SIZE 512MB
MAX_MEMORY_CACHE_COUNT 500
MAX_FILE_CACHE_SIZE 1GB

Request 参数

参数 类型 是否必填 说明
url string 图片 URL、本地文件路径或 rawfile 路径。
imageFit ImageFit 图片缩放模式。
width number 目标宽度,单位 vp。
height number 目标高度,单位 vp。
context common.UIAbilityContext UI 上下文。
state RequestState 请求状态。
imageVerion number 组件复用版本号,用于避免旧请求回调覆盖新组件状态。
uniqueID string 稳定资源 ID,优先用于缓存 Key。
placeholder string 本地占位图路径。
crop boolean 是否将结果图裁剪到目标宽高。
isVideo boolean 是否按本地视频处理。
frameUs number 视频截帧时间,单位微秒。
onLoad Function 图片加载回调。
desiredSize Size 结果图目标尺寸。
bigLevelFiles string[] 可复用的更大档位图本地缓存路径。

支持的资源路径

类型 示例
网络图片 https://example.com/image.jpg
rawfile 图片 images/demo.jpg
本地图片 /data/storage/el2/base/files/demo.jpg
本地视频 配合 isVideo: true 使用本地视频路径

混淆配置

库模块已提供:

  • imageLoader/obfuscation-rules.txt
  • imageLoader/consumer-rules.txt

如果应用开启混淆,请确认三方库导出的类型和自定义 Key 实现没有被误混淆。当前库会保留主要对外 API、DTO、常量和 spark-md5 文件路径。

示例工程

仓库内 entry 模块包含 demo 页面:

  • pages/Index:导航页、缓存大小展示、清除缓存。
  • pages/ImageLoaderDemoPage:使用 image_loader 的瀑布流图片页面。
  • pages/NativeImageDemoPage:使用系统 Image 的普通图片瀑布流页面。

注意事项

  • 建议在应用启动阶段只初始化一次 ImageLoader
  • 网络图片建议使用 HTTPS,避免明文 HTTP 带来的中间人风险。
  • 列表场景中请在组件销毁或回收时调用 cancel(request),并通过 imageVerion 避免复用错位。
  • 如果同一资源的 URL 会变化,请传入稳定的 uniqueID
  • gif / webp 动图会以 base64 字符串形式回调,可直接传给系统 Image
  • 磁盘缓存位于 context.cacheDir 下,系统可能在空间紧张时清理该目录。

License

Apache-2.0. See LICENSE.

See NOTICE for attribution notices.

This project includes third-party software. See THIRD_PARTY_NOTICES.md.

About

一款用于 HarmonyOS 应用的图片加载与缓存三方库,提供网络图片下载、本地图片解码、视频封面提取、内存缓存、磁盘缓存、并发控制和自定义缓存 Key 等能力。

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors