鴻蒙HarmonyOS UI框架關鍵技術解析
HarmonyOS UI框架提供了界面繪制相關的處理方法,例如:圖形控件、頁面布局和窗口管理(如圖1所示)。

圖1 UI框架
HarmonyOS UI框架采用的是ACE(Ability Crossplatform Environment)框架(如圖2所示)。
ACE是一個應用開發框架,在OS架構之上,屬于上層框架,目前支持JAVA和JS語言開發,兩種語言框架具體區別如下:
1. JAVA UI框架提供了細粒度的UI編程接口,使應用開發更加靈活,元素以組件、布局的形式將界面繪制在窗口上。
2. JS UI框架采用類HTML和CSS聲明式編程語言作為頁面布局和頁面樣式的開發語言,頁面業務邏輯則支持ECMAScript 規范的JavaScript語言。JS UI框架提供的聲明式編程,可以讓開發者避免編寫UI狀態切換的代碼,視圖配置信息更加直觀。

圖2 ACE UI框架
HarmonyOS UI框架關鍵技術
ACE JAVA UI框架
應用由Ability構成。Ability可以分為FA(Feature Ability)和PA(Particle Ability)兩種類型。
❖Feature Ability(簡稱FA)支持Page Ability,一般用于用戶交互,在屏幕上顯示一個用戶界面,該界面用來顯示所有可被用戶查看和交互的內容。用戶界面由UI元素構成,通常包含布局、控件等形式,且元素支持設置資源和動畫。
❖Particle Ability支持Data Ability(數據訪問)和Service Ability(后臺服務),一般用于后臺業務邏輯的實現。

圖3 JAVA UI
一 . 界面構成
每個用戶界面的UI元素由組件樹構成,即由Component和ComponentContainer對象構成(如圖4所示)。
Java UI框架提供了一部分Component和ComponentContainer的具體子類,即創建用戶界面(UI)的各類組件,包括一些常用的組件(比如:文本、按鈕、圖片、列表等)和常用的布局(比如:DirectionalLayout和DependentLayout)等。用戶可通過組件進行交互操作,并獲得響應。
● Component: 提供內容顯示,是界面中所有組件的基類。
●ComponentContainer: 作為容器容納Component或ComponentContainer對象,并對它們進行布局。

圖4 JAVA UI組件樹
二.Ability
Page Ability的構成
一個Page可以由一個或多個AbilitySlice構成,AbilitySlice是指應用的單個頁面及其控制邏輯的總和。

圖5 Page Ability構成
Ability的生命周期
● onStart()
當系統首次創建Page實例時,觸發該回調。
● onActive()
Page會在進入INACTIVE狀態后來到前臺,然后系統調用此回調。Page在此之后進入ACTIVE狀態,該狀態是應用與用戶交互的狀態。
● onInactive()
當Page失去焦點時,系統將調用此回調,此后Page進入INACTIVE狀態。
● onBackground()
如果Page不再對用戶可見,系統將調用此回調,此后Page進入BACKGROUND狀態。
● onForeground()
處于BACKGROUND狀態的Page仍然駐留在內存中,當重新回到前臺時,系統將先調用onForeground()回調通知開發者,而后Page的生命周期狀態回到INACTIVE狀態。
● onStop()
下面是幾個主要生命周期函數。
系統將要銷毀Page時,將會觸發此回調函數。
具體生命周期流程如下圖所示:

圖6 Java FA生命周期
Java Ability路由
Java FA提供三種路由方式:
- Ability間的跳轉(不同Ability)
- Ability內部AbilitySlice間跳轉
- 跨設備跳轉

圖7 Java FA路由
1.Ability間跳轉(不同Ability):
一個Ability跳轉到另一個Ability時,根據不同的action選擇不同的Slice。示例代碼如下:
- Intent intent = new Intent();
- Operation operation = new Intent.OperationBuilder()
- .withAction("action2")
- .build();
- intent.setOperation(operation);
- startAbility(intent);
如圖7為示,Ability3通過addActionRoute接口配置了3條路由規則Router:
- action1路由到AbilitySlice1;
- action2路由到AbilitySlice2;
- action3路由到AbilitySlice3。
Ability1和Ability2分別通過startAbility跳轉到Ability3,再根據三條路由規則選擇各自對應的AbilitySlice。
其時序如圖8所示:

圖8 Ability間跳轉
- Ability2初始化時通過addActionRoute接口設置了路由規則。
- Ability1通過startAbilityForResult跳轉到Ability2時,Ability2根據action選擇AbilitySlice1或AbilitySlice2。
- 當Ability2關閉返回時,Ability1通過onAbilityResult()回調方法,對請求結果進行處理。
2.Ability內部AbilitySlice間跳轉
當發起導航的AbilitySlice和導航目標的AbilitySlice處于同一個Ability時,可以通過present()或presentForResult()方法實現導航。
同一個Page內的AbilitySlice導航,只需要指定目標AbilitySlice名稱即可。AbilitySlice1通過present方法發起跳轉,并指定目標名為AbilitySlice2,則跳轉結果為顯示AbilitySlice2。示例代碼如下:
- present(new AbilitySlice2(), new Intent());
其時序如圖9所示:

圖9 AbilitySlice間跳轉
- Ability3包含AbilitySlice1、AbilitySlice2、AbilitySlice3三個AbilitySlice,初始化時通過setMainRoute方法設置了默認界面為AbilitySlice1。
- AbilitySlice1可通過present()發起導航到AbilitySlice2,導航完成后界面顯示AbilitySlice2。
- 若AbilitySlice1希望從導航目標AbilitySlice3返回時,能夠獲得其返回結果,則可使用presentForResult()實現導航。當AbilitySlice3返回時,系統將回調onResult()給AbilitySlice1來接收和處理返回結果,其中返回結果由AbilitySlice3在其生命周期內通過setResult()進行設置。
3.跨設備跳轉
Ability也支持跨設備的路由,即目標Ability即可以是本地設備的Ability,亦可以是同一用戶的不同設備,只需在startAbility進行路由時通過withDeviceId指定對端的設備id即可。
如圖10所示:Ability1通過action選擇到Ability2的路由,且通過withDeviceId指定了目標設備B,則最終結果為設備B上Ability2的對應界面被拉起顯示。

圖10 跨設備路由
4.資源管理
JAVA UI框架下的資源管理目錄如下:

圖12 JAVA UI下資源目錄結構


示例代碼如下:
Java文件中,引用string.json文件中類型為“String”、名稱為“app_name”的資源:
- ohos.global.resource.ResourceManager resManager = this.getResourceManager();
- String result = resManager.getElement(ResourceTable.String_app_name).getString();
XML文件中,引用string.json文件中類型為“String”、名稱為“app_name”的資源:
- <?xml version="1.0" encoding="utf-8"?>
- <DirectionalLayout xmlns:ohos="http://schemas.huawei.com/res/ohos"
- ohos:width="match_parent"
- ohos:height="match_parent"
- ohos:orientation="vertical">
- <Text ohos:text="$string:app_name"/>
- </DirectionalLayout>
ACE JS UI框架
JS UI框架是一種跨設備的高性能UI開發框架,支持聲明式編程和跨設備多態UI。它包括應用層(Application)、前端框架層(Framework)、引擎層(Engine)和平臺適配層(Porting Layer)。

圖13 JS UI框架
❖ Application
應用層表示開發者使用JS UI框架開發的FA應用。
❖ Framework
前端框架層主要完成前端頁面解析,以及提供MVVM(ModelViewViewModel)開發模式、頁面路由機制和自定義組件等能力。
❖ Engine
引擎層主要提供動畫解析、DOM(Document Object Model)樹構建、布局計算、渲染命令構建與繪制、事件管理和平臺channel機制等能力。
❖ Porting Layer
適配層主要完成對平臺層進行抽象,提供具體抽象接口,可以對接到不同系統平臺。比如:事件對接、渲染管線對接和系統生命周期對接等。
1.界面構成
每個用戶界面的 UI布局由HML+CSS文件完成,響應及業務邏輯由JS文件完成。

圖14 JS應用構成
● HML(HarmonyOS Markup Language)是一套類HTML的標記語言,通過組件,事件構建出頁面的內容。頁面具備數據綁定、事件綁定、列表渲染、條件渲染和邏輯控制等高級能力。
● CSS是描述HML頁面結構的樣式語言。
● JS文件用來定義HML頁面的業務邏輯,支持ECMA規范的JavaScript語言。
示例代碼如下:

圖15 JS UI代碼示例
其中,UI布局由HML和CSS完成:
HML里<div>頁簽設置了界面組件,組件樣式由container類定義,組件中包含文本控件text,文本內容由{{title}}填充,并給該文本控件設置了點擊響應事件onclick,在控件被點擊時執行change方法。
CSS里聲明了樣式,如container類設置了HML里
對應的業務邏輯在JavaScript完成:
初始化時,將title設置為“hello world”,即刷新了文本控件text的填充內容{{title}}。
組件(Component)是構建頁面的核心,每個組件通過對數據和方法的簡單封裝,實現獨立的可視、可交互功能單元。

圖16 組件分類
關于【組件詳情】,請參考官網資料:
● 組件詳情
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-js-building-ui-component-0000000000500580
2.Ability
JS UI的Ability生命周期
下面是幾個主要生命周期函數。
● onCreate ()
當應用創建時調用。(應用的生命周期)
● onInit ()
頁面數據初始化完成時觸發,只觸發一次。
● onReady ()
頁面創建完成時觸發,只觸發一次。
● onShow ()
頁面顯示時觸發。
● onHide ()
頁面消失時觸發。
● onDestroy ()
頁面銷毀時觸發。
具體生命周期流程如下圖所示:

圖17 JS FA頁面生命周期
JS Ability路由
JS FA也提供了三種路由方式:
- Ability間的跳轉
- Ability內部JS page間跳轉
- 跨設備跳轉

圖18 JS FA路由
1.Ability間的跳轉
JS中的Ability繼承自AceAbility。
AceAbility間的跳轉JS接口通過FeatureAbility.startAbility完成:
- let actionData = {
- uri: 'www.huawei.com'
- };
- let target = {
- bundleName: "com.example.harmonydevsample",
- abilityName: "com.example.harmonydevsample.EntryJSApiAbility",
- data: actionData
- };
- let result = await FeatureAbility.startAbility(target);
- let ret = JSON.parse(result);
- if (ret.code == 0) {
- console.log('success');
- } else {
- console.log('cannot start browing service, reason: ' + ret.data);
- }
2.Ability內部JS page間跳轉
JS的Ability中可有多個不同頁面,每個界面是一個Js Page(在pages目錄下定義),如下面的ability包含了index和detail 2個頁面:
- {
- ...
- "pages": [
- "pages/index/index",
- "pages/detail/detail"
- ]
- ...
- }
JS Page間可通過router跳轉,例如跳轉到detail的頁面:
- import router from '@system.router';
- router.push({
- uri: "pages/detail/detail",
- params: {
- eventId: item,
- }
- });
3.跨設備跳轉
跨設備跳轉路由原理同Java UI上跨設備一樣,只是JS UI中提供的是對應JS的接口:
- FeatureAbility.startAbility(OBJECT)
- FeatureAbility.startAbilityForResult(OBJECT)
三.資源管理
JS UI框架下的資源管理目錄如下:

圖19 JS UI下資源目錄結構
● app.js文件用于全局JavaScript邏輯和應用生命周期管理。
● pages目錄用于存放所有組件頁面。
● common目錄用于存放公共資源文件,比如:媒體資源,自定義組件和JS文件。
● resources目錄用于存放資源配置文件,比如:全局樣式、多分辨率加載等配置文件。
● i18n目錄用于配置不同語言場景資源內容,比如:應用文本詞條,圖片路徑等資源。資源文件命名為“語言地區.json”格式。
其中,
● .hml結尾的HML模板文件,這個文件用來描述當前頁面的文件布局結構。
● .css結尾的CSS樣式文件,這個文件用于描述頁面樣式。
● .js結尾的JS文件,這個文件用于處理頁面和用戶的交互。
資源引用:

❖ t方法引用資源,t方法引用資源,t既可以在hml中使用,也可以在js中使用,$t參數說明如下:

示例代碼如下:
• enUS.json中定義:
- {
- "strings": {
- "hello": "Hello world!",
- ……
- },
- }
• HML中引用:
- <div>
- <!-- text中顯示“Hello world!” -->
- <text>{{ $t('strings.hello') }}</text>
- </div>
• JS中引用:
- export default {
- data: {
- hello: '',
- },
- onInit() {
- this.hello = this.$t('strings.hello');
- },
- }
❖ 單復數通過tc引用資源,定義單復數資源的內容通過json格式的key為“zero”、“one”、“two”、“few”、“many”和“other”區分,tc引用資源,定義單復數資源的內容通過json格式的key為“zero”、“one”、“two”、“few”、“many”和“other”區分,tc參數說明如下:

示例代碼例如下:
• enUS.json中定義:
- {
- "strings": {
- "people": {
- "one": "one person",
- "other": "{count} people"
- }
- }
- }
• HML中引用:
- <div>
- <!-- 傳遞數值為2時:"2 people" 阿拉伯語中此處匹配key為two的詞條-->
- <text>{{ $tc('strings.people', 2) }}</text>
- </div>
• JS中引用:
- export default {
- data: {
- people: '',
- },
- onInit() {
- this. people = this.$tc('strings.people', 2);
- },
- }
❖ r方法引用資源,r方法引用資源,r既可以在hml中使用,也可以在js中使用,$r參數說明如下:

示例代碼如下:
• resldpi.json中定義:
- {
- "image": {
- "wearable": "common/wearable.png",
- ……
- }
- }
• HML中引用:
- <div>
- <!-- 通過$r來設置對應圖片資源在json配置文件中的path -->
- <image src="{{ $r('image.wearable') }}" class="image"></image>
- </div>
• JS中引用:
- export default {
- private: {
- wearable: '',
- },
- onInit() {
- // 資源格式化:
- this. wearable= this.$r('image. wearable');
- },
- }
最后,本文描述的HarmonyOS應用UI開發方法可以覆蓋大部分簡單業務,開發者可以根據需求自由選擇JS或者JAVA框架來完成。