HarmonyOS服務卡片開發知識總結
前言
服務卡片的征文活動也已經接近尾聲,在這段時間里,論壇里有許多優秀的服務卡片作品和相關的文章涌現。我拜讀了專欄中幾乎所有的服務卡片的開發分享文章,從每一篇文章中提取并汲取精華,整合到本文中。一些較為顯然的介紹性的內容在本文中將會被省略(如卡片有多少種尺寸之類),但是一些即使在很多文章都已經說明過的,而我又認為比較重要的內容,我仍然會再次記錄下來(例如卡片的框架)。另外,作為學習筆記,我會記錄下一些我在學習種遇到的新的名詞的概念,這些概念可能是大家已經熟知的,這部分大家可以直接忽略;文章的內容整合自論壇種的眾多文章,所以大家可能會在本文中看到自己文章的影子。
服務卡片的框架
服務卡片整體框架主要包含三部分:卡片使用方、卡片管理服務和卡片提供方。其概念分別如下:
● 卡片使用方:顯示卡片內容的宿主應用,控制卡片在宿主中展示的位置,如桌面、服務中心、搜索等。
● 卡片管理服務:用于管理系統中所添加卡片的常駐代理服務,包括卡片對象的管理與使用,以及卡片周期性刷新等。
● 卡片提供方:提供卡片顯示內容的HarmonyOS應用或原子化服務,控制卡片的顯示內容、控件布局以及控件點擊事件。
卡片的運行框架有如下示意圖:

簡明版示意圖

詳細版示意圖
卡片的常用功能
Java卡片與JS卡片功能的對比圖

MainAbility的自動生成函數解析
在新建服務卡片的時候,在MainAbility類中將會生成一些回調方法,具體方法及其回調條件如下圖,在后面的具體的卡片操作中,也會再次聲明所調用的回調方法。

在onCreatForm(Intent)方法中,卡片提供方被拉起后intent會攜帶卡片相關信息,具體如下:

服務卡片生命周期回調函數時序如下:

配置卡片編輯功能
有些服務卡片需要具備可編輯能力,如天氣App需要編輯所在城市。具體實現方法如下:在config.json中,對某一個form的配置增加formConfigAbility的屬性配置,可實現編輯功能。formConfigAbility的值是一個url格式的Ability名稱。若不配置formConfigAbility,則不顯示編輯菜單。示例代碼如下:(摘抄自[一文看懂HarmonyOS服務卡片運行原理和開發方法])(https://harmonyos.oss-cn-beijing.aliyuncs.com/images/202106/830a107135e5fa06fa1714ebaa9fa523833da2.jpg?x-oss-process=image/resize,w_1080,h_478)

卡片的定點/定時刷新:將回調updateForm()方法
運作機制示意圖如下:

注意:定時刷新和定點刷新都配置的情況下,定時刷新優先。
JS卡片的定點更新步驟:
1.關閉定時更新:updateDuration”修改為0,以關閉定時刷新(config.json文件中)
2.設定“scheduledUpdateTime”的時刻
3.在具體的xxxxlmpl中重寫updateFormData()方法
4.把需要刷新的數據存入一個ZSONObject實例中
5.將這個實例封裝在一個FormBindingData的實例bindingData中
6.調用MainAbility的方法updateForm(),并將bindingData作為第二個實參。
JS卡片重寫updateFormData()方法的代碼如下:

JAVA卡片的定點更新步驟:
1.前三步與JS卡片相同
2.構造一個ComponentProvider的實例,用于表示一個Java卡片實例,傳入的第一個實參是根據卡片尺寸得到的布局文件。然后,調用方法setText()修改卡片的標題;最后,調用MainAbility的方法updateForm(),并將componentProvider作為第二個實參。
JAVA卡片重寫updateFormData()方法的代碼如下:

卡片的定時刷新
卡片的定時刷新的最小單位時間是三十分鐘,這就帶來了兩個問題:
1.創建卡片后的最初的三十分鐘是不會進行卡片刷新的,所以需要進行手動的刷新。
2.如果是編寫刷新間隔小于三十分的卡片(如時鐘卡片每一秒刷新一次),那么需要自己重新創建一個timer實例來設定刷新時間。
添加手動刷新:用onCreateForm()調用onUpdateForm(formId)即可,代碼摘抄自亮子力的嗶哩嗶哩卡片
- @Override
- protected ProviderFormInfo onCreateForm(Intent intent) {
- ... ...
- //初始化時先在線更新一下卡片
- onUpdateForm(formId);
- return formController.bindFormData();
- }
重新編寫刷新時間的代碼為代碼摘抄自Codelabs 之 時鐘FA卡片開發樣例
- private void startTimer() {
- Timer timer = new Timer();
- timer.schedule(
- new TimerTask() {
- @Override
- public void run() {
- updateForms();
- }
- },
- 0,
- SEND_PERIOD);
- }
- private void updateForms() {
- // 從數據庫中獲取卡片信息
- HiLog.info(LABEL, "從數據庫中獲取卡片");
- OrmPredicates ormPredicates = new OrmPredicates(Form.class);
- List<Form> formList = connect.query(ormPredicates);
- int layoutId=0;
- // 更新時分秒
- if (formList.size() <= 0) {
- return;
- }
- HiLog.info(LABEL, "遍歷卡片列表,逐個更新");
- for (Form form : formList) {
- // 遍歷卡片列表更新卡片
- ComponentProvider componentProvider = ComponentProviderUtils.getComponentProvider(form, this);
- try {
- Long updateFormId = form.getFormId();
- HiLog.info(LABEL, "updateForm,更新卡片[:"+updateFormId+"] 的數據,并非數據庫操作" );
- //更新卡片數據
- boolean isSucc=updateForm(updateFormId, componentProvider);
- HiLog.info(LABEL, "更新卡片數據完成,"+isSucc);
- } catch (FormException e) {
- // 刪除不存在的卡片
- DatabaseUtils.deleteFormData(form.getFormId(), connect);
- HiLog.error(LABEL, "更新卡片異常,刪除數據庫中不存在的卡片");
- }
- }
- }