卡片
1. 卡片概念
- 什么是卡片?
卡片用来显示或者提示一些基本信息或者进行一些基本操作。注意不能做重逻辑,所有重要逻辑全部交给应用
- 如果是元服务如何唤醒?
因为元服务不提供桌面应用图标,我们可以通过用户手动的方式在桌面上添加一张卡片,通过点击卡片来唤起元服务。
2. 创建卡片
在编辑器中创建
选择动态卡片
卡片的特点
:
1.卡片只能承载少量的内容和交互
2. 卡片可以充当元服务icon作为入口,默认提供一张服务卡片作为入口
3. 普通应用也可以添加服务卡片,但默认没有添加卡片
元服务和普通应用的区别
添加卡片
3. ArkTS卡片实现原理
4. ArkTS卡片渲染服务运行原理
5. 卡片的服务通信
5.1 卡片-------> 应用
- 使用postCardAction方法
- 在卡片pages中书写代码
// 卡片的应用
@Entry
@Component
struct WidgetCard {
@State count: number = 10;
build() {
Column() {
Row({ space: 20 }) {
Button('++')
.onClick(() => {
this.count++;
postCardAction(this, {
action: 'call',
abilityName: 'EntryAbility',
params: {
method: 'updateFormCount',
num: this.count
}
})
})
Text(this.count.toString())
.fontSize(18)
Button('--')
.onClick(() => {
if (this.count > 0) {
this.count--;
postCardAction(this,{
action:'call',
abilityName: 'EntryAbility',
params:{
method:'updateFormCount',
num:this.count
}
})
}
})
}
}
.width('100%')
.height('100%')
.onClick(() => {
// 点击唤醒应用
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility'
})
})
}
}
- module.json5添加-保持应用在后台权限
"requestPermissions": [{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
}],
- 应用的entryability中进行接收
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { rpc } from '@kit.IPCKit';
import { JSON } from '@kit.ArkTS';
import { preferences } from '@kit.ArkData';
import { formBindingData, formProvider } from '@kit.FormKit';
const DOMAIN = 0x0000;
//必须是rpc.Parcelable类型
class Params implements rpc.Parcelable {
marshalling(dataOut: rpc.MessageSequence): boolean {
return true;
}
unmarshalling(dataIn: rpc.MessageSequence): boolean {
return true;
}
}
class CardParams {
count: number = 0
formId:string = ""
}
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
this.callee.on("updateFormCount", (data) => {
const res = JSON.parse(data.readString()) as CardParams;
AppStorage.setOrCreate('count', res.count);
//必须返回一个rpc.Parcelable类型
return new Params();
})
}
onDestroy(): void {
//销毁时解除监听
this.callee.off("updateFormCount")
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
}
onForeground(): void {
// Ability has brought to foreground
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
}
onBackground(): void {
// Ability has back to background
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
}
}
- 主页Index.ets
import { preferences } from '@kit.ArkData'
import { formBindingData, formProvider } from '@kit.FormKit'
@Component
@Entry
struct Index {
@StorageLink('count')
count:number = 0
build() {
Column(){
Text('课程太多了')
.fontSize(18)
.fontColor(Color.Orange)
.fontWeight(700)
Row({ space: 20 }) {
Button('++')
.onClick(() => {
this.count++;
})
Text(this.count.toString())
.fontSize(18)
Button('--')
.onClick(() => {
if (this.count > 0) {
this.count--;
}
})
}
}
.backgroundColor(Color.Pink)
.width('100%')
.height('100%')
}
}
总结:如图示
5.2 应用----------->卡片
- 卡片的ability的entryformability的onAddForm方法中添加
onAddForm(want: Want) {
// Called to return a FormBindingData object.
return formBindingData.createFormBindingData({
formId: want.parameters!["ohos.extra.param.key.form_identity"] as string
});
}
- 卡片:WidgetCard.ets 监听formId ,当formId发生变化时,发送至应用
@LocalStorageProp("formId")
@Watch("updateFormId")
formId: string = ""
updateFormId () {
postCardAction(this, {
action: 'call',
abilityName: 'EntryAbility', // 只能跳转到当前应用下的UIAbility
params: {
method: 'updateFormId',
formId: this.formId
}
})
}
- 在ability中通过callee监听方法,将formId存入持久化
this.callee.on("updateFormId", (data) => {
const res = JSON.parse(data.readString()) as CardParams
const store = preferences.getPreferencesSync(this.context, {
name: 'formIdList'
})
const list = JSON.parse(store.getSync("formIdList", "[]") as string) as string[]
if(!list.includes(res.formId)) {
list.push(res.formId)
}
store.putSync("formIdList", JSON.stringify(list))
store.flush()
formProvider.updateForm(res.formId, formBindingData.createFormBindingData({
num: AppStorage.get("num")
}))
return new Params()
})
- 卸载时解除
onDestroy(): void {
this.callee.off("updateNum")
this.callee.off("updateFormId")
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
}
- Index.ets
@StorageLink("num")
@Watch("pushCard")
num: number = 0
pushCard() {
const store = preferences.getPreferencesSync(getContext(), {
name: 'formIdList'
})
const formIdList = JSON.parse(store.getSync("formIdList", "[]") as string) as string[]
if (formIdList && formIdList.length) {
formIdList.forEach((formId) => {
formProvider.updateForm(formId, formBindingData.createFormBindingData({
num: this.num
}))
})
}
}
- 卡片:从推送的数据中从新获取
@Entry
@Component
struct WidgetCard {
//修改成@LocalStorageProp
@LocalStorageProp("count")
count: number = 0;
@LocalStorageProp("formId")
@Watch("updateFormId")
formId:string = ""
//应用===》卡片 需要把formId给到应用
updateFormId(){
postCardAction(this,{
action:'call',
abilityName: 'EntryAbility',
params:{
method:'updateFormId',
formId:this.formId
}
})
}
build() {
Column() {
Row({ space: 20 }) {
Button('++')
.onClick(() => {
this.count++;
postCardAction(this, {
action: 'call',
abilityName: 'EntryAbility',
params: {
method: 'updateFormCount',
count: this.count
}
})
})
Text(this.count.toString())
.fontSize(18)
Button('--')
.onClick(() => {
if (this.count > 0) {
this.count--;
postCardAction(this,{
action:'call',
abilityName: 'EntryAbility',
params:{
method:'updateFormCount',
count:this.count
}
})
}
})
}
}
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
.width('100%')
.height('100%')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility'
})
})
}
}
总结:如图示: