一款用于 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 使用 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 |
| 参数 | 类型 | 是否必填 | 说明 |
|---|---|---|---|
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.txtimageLoader/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下,系统可能在空间紧张时清理该目录。
Apache-2.0. See LICENSE.
See NOTICE for attribution notices.
This project includes third-party software. See THIRD_PARTY_NOTICES.md.