-
-
[原创]【FAQ】HarmonyOS SDK 闭源开放能力 — Form Kit
-
发表于: 6小时前 104
-
1.问题描述:
卡片里的Iamge无法显示网络图片。
解决方案:
通过FormExtensionAbility在元服务卡片上加载网络图片有以下两种方案:
- 方案一:先下载网络图片到本地,参考元服务卡片上加载本地图片示例代码在EntryFormAbility的onAddForm生命周期回调中实现本地文件的刷新。刷新后,在卡片页面通过backgroundImage属性展示EntryFormAbility传递过来的卡片内容。
- 方案二:申请ohos.permission.INTERNET权限,创建HTTP请求,下载网络图片数据并保存到应用的临时文件中,在EntryFormAbility的onFormEvent生命周期回调中实现网络文件的刷新。刷新后,在卡片页面通过backgroundImage属性展示EntryFormAbility传递过来的卡片内容。使用这种方案在元服务卡片上加载网络图片示例代码详见元服务卡片上加载网络图片指南。
2.问题描述:
如何在主应用中获取卡片的添加/移除?
解决方案:
一、卡片添加/移除的场景以及相关卡片生命周期
由于目前卡片添加/移除至桌面目前没有直接完成的回调响应,可以通过onAddForm和onRemoveForm结合记录保存到桌面的卡片,onAddForm/onRemoveForm添加至桌面的生命周期触发流程如下:
- 长按应用图标->服务卡片->打开卡片列表,触发onAddForm (卡片列表中有几张卡片生命周期就会回调onAddForm几次)。例如:打开下面的卡片列表,卡片列表中有3张卡片,可以看到日志中OnAddForm回调了3次。
- 服务卡片列表取消->触发onRemoveForm(卡片列表中有几张卡片生命周期就会回调触发onRemoveForm几次)。 例如:点击x号取消了服务卡片列表,则会出发OnRemoveForm回调3次。
- 服务卡片列表选择->某一张卡片添加到桌面(卡片生命周期onAddForm选中的卡片,onRemoveForm其余卡片)。例如:添加一张卡片至桌面,则会OnAddForm选中的的卡片,OnRemove另外两张卡片。
- 移除某一张卡片(卡片生命周期onRemoveForm移除的卡片)。例如:在桌面移除一张卡片,会OnRemove当前移除的卡片。
综上流程,卡片整个添加至桌面的流程中,中间状态生命周期onAddForm/onRemoveForm会回调多次,但是最终卡片新增还是移除是确定的。
二、实现卡片添加/移除管理以及通知主应用的实现
本方案使用首选项通过在服务卡片中onAddForm/onRemoveForm回调函数中,对formId进行持久化缓存,并在主应用中进行跨进程读取。以下是实现步骤:
- 实现一个公共的单例首选项类以供服务卡片/主应用共同使用,需要注意的是,这里首选项对于跨进程的场景下,需要使用同一个context上下文对象,后面在调用处均使用了this.context.getApplicationContext()保持统一。
import { preferences } from '@kit.ArkData';
export class PreferencesHelper {
private static instance: PreferencesHelper | null = null
private preferences: preferences.Preferences | null = null
private ctx: Context | null = null
private PREFERENCE_NAME:string = "preferences"
private constructor() {}
public static getInstance(ctx: Context) {
if (PreferencesHelper.instance === null) {
PreferencesHelper.instance = new PreferencesHelper()
}
PreferencesHelper.instance.init(ctx)
return PreferencesHelper.instance
}
private init(ctx: Context) {
this.ctx = ctx
this.preferences = preferences.getPreferencesSync(ctx, { name: this.PREFERENCE_NAME})
}
public get(key: string, defaultValue: Array<string>) {
if (!this.preferences) {
return
}
console.log("get ", defaultValue);
let options: preferences.Options = { name: this.PREFERENCE_NAME };
preferences.removePreferencesFromCacheSync(this.ctx, options);
return this.preferences.getSync(key, defaultValue)
}
public put(key: string, defaultValue: preferences.ValueType) {
if (!this.preferences) {
return
}
console.log("put ", defaultValue);
this.preferences.putSync(key, defaultValue)
this.preferences.flushSync()
}
public clear() {
PreferencesHelper.instance = null
this.preferences = null
}
}
- 当长按应用图标拉起应用卡片列表时以及在卡片列表中选择一张服务卡片时,会触发onAddForm,此时将卡片id保存下来:(注意:formlist需要做去重)
// 服务卡片FormExtensionAbility.ets
onAddForm(want: Want) {
console.log('onAddForm')
let ctx = this.context.getApplicationContext()
let formList: Array<string> =
PreferencesHelper.getInstance(ctx).get('formList', []) as Array<string>
if (want.parameters) {
let formId = (want.parameters['ohos.extra.param.key.form_identity']) as string
// 为了保证formId的唯一性,需要对formList去重
!formList.includes(formId) && formList.push(formId)
PreferencesHelper.getInstance(ctx).put('formList', formList)
}
const formData = '';
return formBindingData.createFormBindingData(formData);
}
- 服务卡片列表取消时或者在桌面移除卡片时,会触发onRemoveForm,此时将记录里对应的数据删除,剩余的即是添加到桌面的卡片:(注意:formlist需要做去重)
// 服务卡片FormExtensionAbility.ets
onRemoveForm(formId: string) {
let ctx = this.context.getApplicationContext()
let formList: Array<string> = PreferencesHelper.getInstance(ctx).get('formList', []) as Array<string>
// 为了保证formId的唯一性,需要对formList去重
formList = formList.filter(item => item !== formId)
PreferencesHelper.getInstance(ctx).put('formList', formList)
}
4.然后,在主应用中对formId进行查询:(注意:主应用需要和卡片使用同一个context)
// EntryAbility.ets
build() {
RelativeContainer() {
Text(this.message)
.id('HelloWorld')
}
.height('100%')
.width('100%')
.onClick(()=>{
let formList: Array<string> =
PreferencesHelper.getInstance(this.context.getApplicationContext()).get('formList', []) as Array<string>
console.log("formList size %d", formList.length);
for (let index = 0; index < formList.length; index++) {
const element = formList[index];
console.log("formId %d", element);
}
})
}
3.问题描述:
卡片列表如何展示网络图片?
解决方案:
- 卡片里面没有直接联网的权限,加载网络图片需要先将网络图片下载到本地,下载网络图片需要使用到网络能力,需要申请ohos.permission.INTERNET权限。
let filesDir = context.getApplicationContext().filesDir
let filePath = filesDir + 'xxx.png'
request.downloadFile(context, {
url: 'xxx', // 此处为图片下载地址
filePath,
}).then((downloadTask: request.DownloadTask) => {
downloadTask.on('complete', () => {
console.log('download complete')
})
}).catch((err: BusinessError) => {
console.error(`Invoke downloadTask failed, code is ${err.code}, message is ${err.message}`);
});
- EntryFormAbility中的onFormEvent生命周期回调中实现网络文件的刷新。
// 卡片需要显示图片场景,formData中formImages必填且不可改名,key值与thumb(结构和名称可自定义)的值需保持一致,值为key对应的fd
class News {
thumb?: string = '';
title: string = '';
}
class FormData {
list: News[] = []
formImages?: Record<string, number> = {};
}
onFormEvent(formId: string) {
// 下载网络图片到本地,通过formImages
let imgPath = await download(ctx)
let file = fs.openSync(imgPath)
let imageMap: Record<string, number> = {}
imageMap[imgPath] = file.fd
let res: FormData = {
list: [
{
title: 'new',
thumb: imgPath, // 需要与formImages的key值一致
}
],
formImages: imageMap
}
await formProvider.updateForm(formId, formBindingData.createFormBindingData(res))
fs.closeSync(file)
}
- 在卡片中通过memory:// + fileName的格式展示。
Image('memory://' + item?.thumb)
赞赏
他的文章
赞赏
雪币:
留言: