今日事笔记-harmony版本持续更新

今日事笔记的亮点是桌面组件。

在鸿蒙系统上桌面组件是服务卡片,流程跟安卓类似。

安卓:

WidgetProvider -> RemoveView -> 桌面渲染

鸿蒙:

EntryFormAbility -> formProvider -> Component -> 桌面渲染

不同的地方:

1:数据提供者:

安卓通过RemoveViewService可以做到数据懒加载驱动RemoveView刷新

鸿蒙通过formBindingData驱动数据刷新组件。期间还需要用到LocalStorageProp,这是个单向驱动数据模型,可以装载数据对象。

还要通过dataPreferences持久化保存formId,即卡片id,以便在程序内实时刷新卡片。

这里formId的保存试过其他方式,比如PersistentStorage, MMKV,但好像都不太好使。

2:添加卡片方式:

安卓是的组件是同意从桌面入口桌面小组件添加。华为是直接可见式添加,即添加过程中会模拟添加一次,在EntryFormAbility中打印日志可以看出,预览添加时会生成formId,添加后会移除formId。实际添加到桌面后会最终onAddForm

下面是EntryFormAbility的代码:

import { formBindingData, FormExtensionAbility, formInfo } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import TodoModel from '../db/TodoModel';
import { CardManager, FormDataClass } from './CardManager';
import LogUtils from '../common/LogUtils';
import { DbManager } from '../db/DbManager';
import TodoStatus from '../net/model/TodoStatus';
import { CardConfigParameter } from '../todaytodo/viewmodel/CardConfigParameter';

export default class EntryFormAbility extends FormExtensionAbility {
  onAddForm(want: Want) {
    this.parseFormId(want)
    let data = new FormDataClass()
    data.itemNumber = 0
    data.cardListData = []
    data.cardConfig = new CardConfigParameter()
    return formBindingData.createFormBindingData(data);
  }

  private parseFormId(want: Want) {
    let formId: string = '';
    if (want.parameters) {
      formId = JSON.stringify(want.parameters[formInfo.FormParam.IDENTITY_KEY]);
      CardManager.get().saveCardId(this.context, formId)
    }
  }

  onCastToNormalForm(formId: string) {
    CardManager.get().saveCardId(this.context, formId)
    CardManager.get().updateCard(this.context, formId)
  }

  onUpdateForm(formId: string) {
    CardManager.get().updateCard(this.context, formId)
  }

  onFormEvent(formId: string, message: string) {
    LogUtils.debug("on from event: " + message)
    if (message) {
      let data: object = JSON.parse(message)
      // 处理待办
      if (data['type'] == CardManager.EVENT_DONE) {
        LogUtils.debug("done todo")
        let model: TodoModel = JSON.parse(JSON.stringify(data["item"]))
        DbManager.getInstanceAsync(this.context, (db)=> {
          model.status = TodoStatus.HISTORY
          db.update(model)
          CardManager.get().updateCard(this.context, formId)
          LogUtils.debug("update card success")
        })
      } else if (data['type'] == CardManager.EVENT_ADD) {
        // 添加待办
        LogUtils.debug("add todo event")
      } else {
        LogUtils.debug("enter todo main page")
      }
    }
  }

  onRemoveForm(formId: string) {
    CardManager.get().clearCardId(this.context)
  }

  onAcquireFormState(want: Want) {
    this.parseFormId(want)
    return formInfo.FormState.READY;
  }
};

这里主要捕捉到卡片添加,并初始化一些数据,另一个是接收卡片中的点击事件:

postCardAction(this, {
        action: this.ACTION_TYPE,
        abilityName: this.ABILITY_NAME,
        params: {
          message: this.MESSAGE
        }
      });

postCardAction是卡片组件中特有的一个接口。

对卡片的一些信息持久化和数据更新,写在CardManager中:

import { DbManager } from '../db/DbManager'
import { formBindingData, formProvider } from '@kit.FormKit'
import TodoModel from '../db/TodoModel'
import TodoStatus from '../net/model/TodoStatus'
import LogUtils from '../common/LogUtils'

import dataPreferences from '@ohos.data.preferences';
import EntryContext from 'LibUser/src/main/ets/commons/EntryContext'
import { CardConfigParameter } from '../todaytodo/viewmodel/CardConfigParameter'
import JSON from '@ohmos/json-bigint';

export class FormDataClass {
  title: string = "今日事"
  itemNumber: number = 0
  cardListData: TodoModel[] = []
  cardConfig: CardConfigParameter = new CardConfigParameter()
}

export class CardManager {
  private static instance: CardManager = new CardManager()

  static get(): CardManager {
    return CardManager.instance
  }

  static EVENT_DONE = "event_done"
  static EVENT_ADD = "event_add"
  static EVENT_MAIN = "event_main"
  static KEY_CARD_ID = "card_id"
  static KEY_CARD_CONFIG = "card_config"

  saveCardConfig(context: Context, config: CardConfigParameter) {
    let pref = dataPreferences.getPreferencesSync(context, { name: CardManager.KEY_CARD_ID });
    pref.putSync(CardManager.KEY_CARD_CONFIG, JSON.stringify(config, undefined, undefined))
    pref.flush()
  }

  getCardConfig(context: Context): CardConfigParameter {
    let pref = dataPreferences.getPreferencesSync(context, { name: CardManager.KEY_CARD_ID });
    let cardConfigStr = pref.getSync(CardManager.KEY_CARD_CONFIG, '') as string
    if (cardConfigStr == '') {
      return new CardConfigParameter()
    }
    let cardConfig: CardConfigParameter = JSON.parse(cardConfigStr)
    return cardConfig
  }

  saveCardId(context: Context, formId: string) {
    let pref = dataPreferences.getPreferencesSync(context, { name: CardManager.KEY_CARD_ID });
    pref.putSync(CardManager.KEY_CARD_ID, formId)
    pref.flush()
  }

  clearCardId(context: Context) {
    let pref = dataPreferences.getPreferencesSync(context, { name: CardManager.KEY_CARD_ID });
    pref.putSync(CardManager.KEY_CARD_ID, '')
    pref.flush()
  }

  getFormId(context: Context): string {
    let pref = dataPreferences.getPreferencesSync(context, { name: CardManager.KEY_CARD_ID });
    let cardId = pref.getSync(CardManager.KEY_CARD_ID, '') as string
    return cardId
  }

  updateCard(context?: Context, formId?: string) {
    if (context) {
      DbManager.getInstanceAsync(context, (db) => {
        this.updateCardData(context, db, formId)
      })
    } else {
      this.updateCardData(EntryContext.getContext() as Context, DbManager.getInstance(), formId)
    }
  }

  updateCardData(context: Context, db: DbManager, cardId?: string) {
    if (!cardId) {
      cardId = this.getFormId(context)
    }
    if (cardId) {
      db.getRecordByStatus(TodoStatus.TODAY).then(list => {
        let dataClass = new FormDataClass()
        dataClass.cardListData = Array.from(list)
        dataClass.itemNumber = list.length
        dataClass.cardConfig = this.getCardConfig(context)
        let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(dataClass);
        formProvider.updateForm(cardId, formInfo)
        LogUtils.debug("update card form complete.")
      })
      this.saveCardId(context, cardId)
    } else {
      LogUtils.error("card id is empty")
    }
  }
}

FormDataClass用来做数据通信,把需要配置和动态刷新的数据用FormDataClass来传递。

整个流程就这么多,具体可看源码:github

这里还有个遗留问题:

卡片背景透明度不知道怎么设置,看FA模型的网上有方案,但Stage不知道咋处理。直接设置Component的最外层组件背景色不生效。应该是外面还有一层包裹。

相关推荐
SoraLuna1 小时前
「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现
macos·ui·harmonyos
ClkLog-开源埋点用户分析2 小时前
ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力
华为·开源·开源软件·harmonyos
mg6682 小时前
鸿蒙系统的优势 开发 环境搭建 开发小示例
华为·harmonyos
lqj_本人3 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人3 小时前
使用 Flutter 绘制一个棋盘
harmonyos
lqj_本人6 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
青瓷看世界7 小时前
华为HarmonyOS打造开放、合规的广告生态 - 插屏广告
华为·harmonyos·广告投放
青瓷看世界8 小时前
华为HarmonyOS借助AR引擎帮助应用实现虚拟与现实交互的能力2-管理AR会话
华为·ar·harmonyos·虚拟现实
2301_795558648 小时前
鸿蒙的进化史
华为·harmonyos
Swift社区8 小时前
HarmonyOS App 购物助手工具的开发与设计
harmonyos·arkts·arkui