堅果派由堅果創建,團隊擁有 12 個華為 HDE,以及若干其他領域的三十余位萬粉博主運營。 團隊成員聚集在北京,上海,南京,深圳,廣州,寧夏等地,歡迎合作。
首先鋪墊兩個基礎知識:
1.為什么桌面卡片需要使用特殊機制來刷新?
主要有兩個原因:第一是 OpenHarmonyOS Api9 的桌面卡片出于降低系統能耗的目的,被限制了只有 5 秒的活動時間。超過 5 秒以后桌面卡片的相關進程會被強制銷毀,變成一個靜態的頁面。只有通過 router 機制、call 機制或者 message 機制拉起相關后臺,才能再次進行卡片內容的刷新。
第二個原因是從實際的運行機制來說,桌面卡片實際上并不是應用主體的一部分,而是歸屬于 OpenHarmony 系統中的桌面應用所管理的一系列服務,桌面卡片與其對應的應用主體之間相互隔離,只能使用專門的接口來進行數據交互與頁面管理。
每張卡片都有一個獨立的 LocalStorage 可以用來存儲頁面級變量,但同一個 LocalStorage 的數據只能在 UIAbility 內部共享,對外隔離,UIAbility 無法直接訪問。
桌面卡片刷新機制的本質就是通過專門的接口,改變特定桌面卡片的 LocalStorage 參數。以實現桌面卡片的 UI 更新。
2.router 機制、call 機制與 message 機制有什么不同?
這三個機制都可以用來刷新桌面卡片的,三種機制的數據都以 JSON 的格式進行配置,并使用**formBindingData.createFormBindingData()**函數構建數據對象。
主要區別在于:
router 機制會直接打開應用界面,效果有點像點擊桌面圖標。也可以帶參數打開應用,直接進入應用內部的某個特定位置,或者觸發某項功能。
call 機制是不打開應用界面,僅在后臺拉起應用主體的 UIAbility,來執行 UIAbility 內部的相關代碼。call 機制不受 5 秒時長的限制,可以先實現復雜且費時的數據加載,再提供給桌面卡片進行刷新。
message 機制則不涉及到應用的 UIAbility,只是拉起桌面卡片自己的 FormAbility,也可以刷新卡片,但仍然受 5 秒時長的限制,更適合輕量化的的實現卡片內容的刷新。
接下來進入正式講解:
本案例使用 call 機制,通過拉起應用主體的方式來刷新卡片內容。
使用 call 機制刷新卡片的全流程主要分為 3 個階段:
1.通過卡片的 postCardAction 接口觸發 call 事件 →
2.call 事件拉起應用主體的后臺,進行數據準備,通過 updateForm 接口執行刷新事件 →
3.卡片 page 頁面接收到數據,更新卡片界面。
由于卡片與應用主體是獨立運作的,并且一個應用可能會有多個應用卡片,應用其實并不知到是哪個卡片觸發了 call 事件,所以我們需要把卡片 id 作為參數一起寫入接口,讓卡片的管理方能找到我們要刷新的卡片。
補全以后的全流程如下:
1.(卡片創建時)FormAbility 獲取卡片的 FormID,將其作為參數交給卡片頁面儲存 →
2.卡片頁面初始化自己的 FromID
3.(點擊刷新時)卡片通過 postCardAction 接口觸發 call 事件,將卡片的 FormID 與要執行的函數名 method 都作為參數提交,由系統啟動對應應用的 UIAbility→
4.UIAbility 啟動成功,通過預置的觸發器執行 method 對應的函數,完成數據準備后通過 updateForm 接口將數據推送給卡片管理方 →
5.對應 FormID 的卡片檢測并同步到數據變動,完成頁面變更。
案例代碼:
1.卡片創建時 FormAbility 獲取 FormID,并交給卡片頁面
import formBindingData from '@ohos.app.form.formBindingData'; import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility'; export default class EntryFormAbility extends FormExtensionAbility { onAddForm(want) {//創建卡片時產生的want中包含FormID,需要再此處讀取出來同步給LocalStorage。 let formId = want.parameters["ohos.extra.param.key.form_identity"]; let dataObj1 = { "formId": formId }; let obj1 = formBindingData.createFormBindingData(dataObj1); return obj1; } };
?
2.卡片頁面初始化自己的 FromID
let storage = new LocalStorage(); @Entry(storage) @Component struct WidgetCard { @LocalStorageProp('formId') formId: string = '0';//在Form頁面中使用@LocalStorageProp來進行FromID變量的初始化 }
?
3.卡片通過 postCardAction 接口觸發 call 事件,讓系統拉起應用后臺的 pageAbility
let storage = new LocalStorage(); @Entry(storage) @Component struct WidgetCard { @LocalStorageProp ("formId") @Watch('firstFresh') formId:string='0'//此處使用一個watch裝飾器,在FormID初始化完成后實現第一次的數據刷新。 @LocalStorageProp('text')movieName: string = '加載中...'; @LocalStorageProp('imgName')imgName: string = 'imageName'; firstFresh(){ console.log('卡片初始化') postCardAction(this, { "action": 'call', "abilityName": this.ABILITY_NAME, "params": { "method":"funA", "formId":this.formId, } }); } build() { Column() { Button('刷新') .height('15%') .onClick(() => { postCardAction(this, { "action": 'call',//call事件 "abilityName": 'EntryAbility',//指向目標應用的Ability "params": { "method":"funA",//UIAbility中注冊的用于刷新卡片的事件 "formId":this.formId,//卡片自身的FormID } }); }) } } ?
4.pageAbility 啟動,執行對應的函數,完成數據準備后通過 updateForm 接口將數據推送給卡片管理方
(數據來源于對應的 severless 服務器,為方便演示,severless 的安全機制設為了不做身份校驗即可訪問數據的形式)
注意:callee 監聽事件必須要先申請"ohos.permission.KEEP_BACKGROUND_RUNNING"權限才能正常運行!!!
import UIAbility from '@ohos.app.ability.UIAbility'; import formBindingData from '@ohos.app.form.formBindingData'; import formProvider from '@ohos.app.form.formProvider'; import hilog from '@ohos.hilog'; import Window from '@ohos.window'; import abilityAccessCtrl from '@ohos.abilityAccessCtrl'; import {AGCCloudDB} from'../services/AGCCloudDB' import {AGCStorageReference} from'../services/Storage' import request from '@ohos.request'; import fs from '@ohos.file.fs'; export default class EntryAbility extends UIAbility { onCreate(want, launchParam) {//如果觸發call事件時UIAbility未啟動,會先執行onCreate再執行監聽事件。如果觸發Call事件時UIAbility已經在運行中則直接執行監聽事件。 this.callee.on('funA',(str)=>{//監聽器,檢測到對應參數就執行回調函數 let params = JSON.parse(str.readString()) if (params.formId != undefined) { let formId = params.formId const agcCloudDB = AGCCloudDB.instance(this.context) agcCloudDB.init(this.context).then((res) => { let CloudDB = new AGCStorageReference(this.context) agcCloudDB.getMovie().then((allRecords) => {//從數據庫獲取數據組 let radomNumber = Math.floor(Math.random() * allRecords.length) CloudDB.getDownloadUrl(allRecords[radomNumber].movieName).then((url) => {//從數據組中隨機抽取一項,獲取對應的圖片下載鏈接 let tempDir = this.context.getApplicationContext().tempDir; let tmpFile = tempDir + '/file' + Date.now(); request.downloadFile(this.context, {//將圖片下載到本地,并得到本地的圖片地址 url: url, filePath: tmpFile }).then((task) => { task.on('complete', function callback() { console.info('ArkTSCard download complete:' + tmpFile); let file; try { file = fs.openSync(tmpFile); } catch (e) { console.error(`openSync failed: ${JSON.stringify(e)}`); } console.log(JSON.stringify(allRecords)) let formData = {//進行數據打包 "text": allRecords[radomNumber].movieName, "imgName": allRecords[radomNumber].movieName, 'formImages': {}, } formData.formImages[allRecords[radomNumber].movieName]=file.fd//由于Image的刷新機制必須接受不同的值才能識別到image變化,因此movieName只能使用變量的形式寫入。 let formInfo = formBindingData.createFormBindingData(formData)//創建FormBindingData對象 formProvider.updateForm(formId, formInfo) })//執行updateForm事件,刷新指定卡片。 task.on('fail', function callBack(err) {//數據準備失敗時顯示的內容 console.info('ArkTSCard download task failed. Cause:' + err); let formInfo = formBindingData.createFormBindingData({ 'text': '刷新失敗,請重試' }) formProvider.updateForm(formId, formInfo) }) }) return null }) }) }) } }) } }
?
5.對應 FormID 的卡片收到新的數據,完成頁面變更。
let storage = new LocalStorage(); @Entry(storage) @Component struct WidgetCard { @LocalStorageProp ("formId") @Watch('firstFresh') formId:string='0' @LocalStorageProp('text')movieName: string = '加載中...'; @LocalStorageProp('imgName')imgName: string = 'imageName'; //LocalStorageProp檢測到text與imgName變量發生改變,單向同步最新的數據,并觸發卡片頁面的文本與圖片刷新。 build() { Column() { Text(this.text) .fontSize('12vp') .textAlign(TextAlign.Center) .width('100%') .height('15%') Row() { Image('memory://' + this.imgName)//imgName變化以后image組件會自動尋找對應的圖片進行加載 .width('50%') .height('50%') .margin('5%') }.alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) Button('刷新') .height('15%') .onClick(() => { postCardAction(this, { "action": 'call', "abilityName": 'EntryAbility', "params": { "method":"funA",//UIAbility中注冊的用于刷新卡片的事件 "formId":this.formId, } }); }) } .width('100%').height('100%') .alignItems(HorizontalAlign.Center) .padding('5%') } } ?
postCardAction 接口 call 事件的寫法如下:
updateForm 接口的寫法如下:
為了能讓大家更好的學習鴻蒙 (OpenHarmony) 開發技術,這邊特意整理了《鴻蒙 (OpenHarmony)開發學習手冊》,希望對大家有所幫助:
《鴻蒙(Harmony OS)開發學習手冊》
入門必看:https://docs.qq.com/doc/DUk51cHZJaUpmSlhH
1.應用開發導讀(ArKTS)
2.……
HarmonyOS概念:https://docs.qq.com/doc/DUk51cHZJaUpmSlhH
1.系統定義
2.技術框架
3.技術特性
4.系統安全
快速入門:https://docs.qq.com/doc/DUk51cHZJaUpmSlhH
1.基本概念
2.構建第一個ArkTS應用
3.…
開發基礎知識:https://docs.qq.com/doc/DUk51cHZJaUpmSlhH
1.應用基礎知識
2.配置文件
3.應用數據管理
4.應用安全管理
5.應用隱私保護
6.三方應用調用管控機制
7.資源分類與訪問
8.學習ArkTS
9…
基于ArkTS 開發:https://docs.qq.com/doc/DUk51cHZJaUpmSlhH
1.Ability開發
2.UI開發
3.公共事件與通知
4.窗口管理
5.媒體
6.安全
7.網絡與鏈接
8.電話服務
9.數據管理
10.后臺任務(Background Task)管理
11.設備管理
12.設備使用信息統計
13.DFX
14.國際化開發
15.折疊屏系列
16………
審核編輯 黃宇
-
鴻蒙
+關注
關注
57文章
2369瀏覽量
42900 -
HarmonyOS
+關注
關注
79文章
1979瀏覽量
30280 -
OpenHarmony
+關注
關注
25文章
3728瀏覽量
16395
發布評論請先 登錄
相關推薦
評論