HarmonyOS 鸿蒙Next SaveButton保存图片 媒体图库未实时刷新问题如何定位
HarmonyOS 鸿蒙Next SaveButton保存图片 媒体图库未实时刷新问题如何定位
【问题现象】
使用SaveButton保存图片时,媒库不能实时刷新展示新图片,必须将App关闭才能在相册中看到图片。
【背景知识】
1、SaveButton组件
SaveButton组件允许用户通过点击按钮临时获取存储权限,无需额外的编写权限申请代码。当用户点击该控件时,应用会获得10秒内单次访问媒体库特权接口的授权。这适用于任何需要将文件保存到媒体库的应用场景,例如保存图片或视频等。
2、图片处理服务
- Image Kit是一个用于图片处理和显示的服务,它提供了一系列的功能和工具,帮助开发者在鸿蒙应用中高效地处理和展示图片,主要功能包括图片解码、图片处理、图片编码;
- ImagePacker主要用于图片编码,图片编码指将PixelMap编码成不同格式的存档图片,当前支持打包为JPEG、WebP、png和 HEIF(不同硬件设备支持情况不同) 格式,用于后续处理,如保存、传输等,涉及的api为@ohos.multimedia.image(图片处理);
- packToFile:指定打包参数,将PixelMap图片源编码后直接打包进文件,需要注意的是:使用packToFile方法,需要调用imagePacker.release主动释放imagePacker,打开图库时才能看到新存入的图片。
【定位思路】
媒体库需要在全部file文件的fd都close后才会刷新图库。如果使用packToFile方法,需要调用release主动释放ImagePacker,此时imagePacker内的fd也会close,媒体库才会刷新,打开图库才能看到新存入的图片。
【解决方案】
ArkTS有内存回收机制,ImagePacker对象不调用release方法,内存最终也会由系统统一释放。但图片使用的内存往往较大,为尽快释放内存,建议应用在使用完成后主动调用release方法提前释放内存,代码示例如下:
(1)导入必要模块:
import { resourceManager } from '@kit.LocalizationKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { image } from '@kit.ImageKit';
import { promptAction } from '@kit.ArkUI';
import { fileIo } from '@kit.CoreFileKit';
(2)关键类SavePixelMapToAlbum及函数:
[@Entry](/user/Entry)
[@Component](/user/Component)
export struct SavePixelMapToAlbum {
[@State](/user/State) saveButtonOptions: SaveButtonOptions = {
icon: SaveIconStyle.FULL_FILLED,
text: SaveDescription.SAVE,
buttonType: ButtonType.Capsule
};
[@State](/user/State) pixel: image.PixelMap | undefined = undefined;
[@State](/user/State) albumPath: string = '';
[@State](/user/State) photoSize: number = 0;
private context: Context = getContext(this);
async aboutToAppear() {
const resourceMgr: resourceManager.ResourceManager = this.context.resourceManager;
const fileData: Uint8Array = await resourceMgr.getMediaContent($r(‘app.media.app_icon’).id);
let buffer = new Uint8Array(fileData).buffer as object as ArrayBuffer;
let imageResource = image.createImageSource(buffer);
let opts: image.DecodingOptions = { editable: true };
this.pixel = await imageResource.createPixelMap(opts);
}
async saveSnapshot() {
try {
const context = getContext(this);
let helper = photoAccessHelper.getPhotoAccessHelper(context);
let uri = await helper.createAsset(photoAccessHelper.PhotoType.IMAGE, ‘png’)
let file = await fileIo.open(uri, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
// 写入文件
const imagePackerApi: image.ImagePacker = image.createImagePacker();
let packOpts: image.PackingOption = { format: ‘image/png’, quality: 100 };
imagePackerApi.packToFile(this.pixel, file.fd, packOpts).finally(() => {
//指定打包参数,将PixelMap图片源编码后直接打包进文件
fileIo.close(file.fd).finally(() => {
promptAction.showToast({ message: ‘图片保存成功!’ })
imagePackerApi.release() //主动调用release方法释放内存
})
})
} catch (error) {
}
}
build() {
Column() {
Image(this.pixel)
.objectFit(ImageFit.None)
.height(‘30%’)
SaveButton(this.saveButtonOptions)
//点击保存图片
.onClick(async (event, result: SaveButtonOnClickResult) => {
if (result === SaveButtonOnClickResult.SUCCESS) {
this.saveSnapshot()
}
})
}
.justifyContent(FlexAlign.Start)
.height(‘100%’)
.width(‘100%’)
}
}
【总结】
(1)ArkTS有内存自动回收机制,数据类型分为两类,简单类型和引用类型。简单类型内容直接保存在栈(Stack)中,由操作系统自动分配和释放。引用类型保存在堆(heap)中,需要引擎进行手动释放。GC就是针对堆空间的内存自动回收的管理机制。
(2)在开发过程中,碰到内存使用较大的业务场景,需要主动尽快释放内存,有效地进行内存管理和避免内存泄漏,提高应用的性能和稳定性,例如:
- 使用on注册回调,需要及时进行off释放
- 注册媒体查询,需要解注册
- 自定义弹窗即将析构销毁时将dialogControlle置空
更多关于HarmonyOS 鸿蒙Next SaveButton保存图片 媒体图库未实时刷新问题如何定位的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS 鸿蒙Next SaveButton保存图片 媒体图库未实时刷新问题如何定位的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
针对HarmonyOS 鸿蒙Next中SaveButton保存图片后媒体图库未实时刷新的问题,以下是一些定位步骤:
-
检查权限:
- 确认应用已正确申请并获得了存储权限,因为未获得相应权限可能导致文件无法写入。
-
验证保存路径:
- 确保图片被保存在系统认可的图片存储目录下,否则系统可能无法识别新保存的图片。
-
监听相册变更:
- 尝试使用系统提供的广播或内容观察者机制,监听相册内容的变更,从而触发相册的刷新。
-
调用媒体扫描接口:
- 在保存图片后,调用系统的媒体扫描接口(如MediaScannerConnection.scanFile),确保系统能够立即识别新保存的图片。
-
检查代码逻辑:
- 仔细检查SaveButton的点击事件处理逻辑,确保图片保存操作正确无误,并且在保存后触发了必要的刷新机制。
如果以上步骤均正确无误,但问题依旧存在,可能是由于系统缓存或特定版本的bug导致。此时,可以尝试清除应用缓存或重启设备看是否能解决问题。如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html。