鸿蒙Ability(一):Feature Ability的Page Ability模板
鴻蒙Ability
- 導語
- Ability概念
- Feature Ability
- Page與AbilitySlice
- 在Page Ability中用代碼編寫界面
- 生命周期
- Page Ability生命周期
- AbilitySlice生命周期
- 生命周期示例
- 生命周期示例之同一Page跳轉
- 生命周期示例之不同Page跳轉
- AbilitySlice間的導航
- AbilitySlice路由配置
- 同一Page內導航
- 跳轉不攜帶數(shù)據(jù)
- 跳轉并攜帶數(shù)據(jù)
- 跳轉并返回數(shù)據(jù)
- 不同Page間導航
- 根據(jù)Ability的全稱啟動應用
- 根據(jù)Operation的其他屬性啟動應用
- Intent
導語
在鴻蒙應用中在創(chuàng)建一個Page Ability(Feature Ability)時(Page Ability可以理解為安卓的Acitvity),會生成兩個類:“XxxAbility”和“XxxAbilitySlice”,和一個布局文件“ability_Xxx.xml”。
為什么創(chuàng)建Ability的時候,會有三個選項呢?還會自動生成AbilitySlice呢?
這就涉及到鴻蒙中一個很重要的概念——Ability
Ability概念
Ability是應用的重要組成部分,是應用所具備能力的抽象。一個應用可以具備多種能力(即可以包含多個Ability)。Ability可以分為FA(Feature Ability)和PA(Particle Ability)兩種類型。
①Feature Ability
FA代表有界面的Ability,支持Page Ability模板(是FA唯一支持的模板),用于提供與用戶交互的能力。
②Particle Ability
PA代表無界面的Ability,支持Service Ability和Data Ability模板。
Service模板用于提供后臺運行任務的能力,
Data模板用于對外部提供統(tǒng)一的數(shù)據(jù)訪問抽象。
在配置文件config.json中注冊Ability時,可以通過配置Ability元素中的“type”屬性來指定Ability模板類型。
“type”的取值可以為“page”(代表Page模板)、“service”(代表Service模板)或“data”(代表Data模板)。
Feature Ability
Page與AbilitySlice
Page模板是Feature Ability唯一支持的模板。一個Page實例可以包含一組相關頁面,每個頁面用一個AbilitySlice實例表示。
在Feature Ability中,有一個很重要的概念就是AbilitySlice,一個Feature Ability可以由一個或多個AbilitySlice構成。
AbilitySlice是Feature Ability的組成單元,是指應用的單個可視化界面及其交互邏輯的總和。一個Feature Ability可以包含一組業(yè)務關系密切的可視化界面,每一個可視化界面對應一個AbilitySlice。
可以這么說:Feature Ability本質上就是一個頁面,可以稱為Page Ability(后文將稱Feature Ability為Page Ability),這里的Page可以理解為Android中的Activity,Abilityslice可以理解為Android中的Layout。
Ability可以有界面(如Feature Ability),也可以沒有界面(如Particle Ability)
有界面要顯示時,在Ability中,通過setMainRoute關聯(lián)要顯示的AbilitySlice(XxxAbility通過SetMainRoute關聯(lián)XxxAbilitySlice)
設置布局文件、處理業(yè)務邏輯的代碼寫在AbilitySlice中(和布局文件ability_xxx.xml關聯(lián)的是XxxAbilitySlice)
在Page Ability中用代碼編寫界面
public class CodeWritePageAbilitySlice extends AbilitySlice {@Overridepublic void onStart(Intent intent) {super.onStart(intent);//super.setUIContent(ResourceTable.Layout_ability_code_write_page);// 使用代碼生成 UI 布局與組件// 聲明布局 創(chuàng)建相對布局, 傳入當前界面 Ability 對象DirectionalLayout directionalLayout = new DirectionalLayout(this);// 設置布局大小directionalLayout.setWidth(MATCH_PARENT);directionalLayout.setHeight(MATCH_PARENT); // // 創(chuàng)建布局配置對象DirectionalLayout.LayoutConfig // // 構造函數(shù)中傳入寬高設置 // DirectionalLayout.LayoutConfig layoutConfig = new DirectionalLayout.LayoutConfig( // DirectionalLayout.LayoutConfig.MATCH_PARENT, // DirectionalLayout.LayoutConfig.MATCH_PARENT); // // 將布局配置對象設置給布局對象 // directionalLayout.setLayoutConfig(layoutConfig);// 設置水平方向directionalLayout.setOrientation(Component.HORIZONTAL);// 設置布局背景為淡藍色// 創(chuàng)建背景元素ShapeElement shapeElement = new ShapeElement();// 設置淡藍色shapeElement.setRgbColor(new RgbColor(187, 255, 255));// 設置頁面背景顏色(將背景設置給布局)directionalLayout.setBackground(shapeElement);// 創(chuàng)建一個Text文本組件Text text = new Text(this);// 設置文本的布局// 創(chuàng)建布局配置對象DependentLayout.LayoutConfig// 在構造函數(shù)中傳入寬高設置,這里設置成寬800、高自適應DependentLayout.LayoutConfig textLayoutConfig = new DependentLayout.LayoutConfig(800, DependentLayout.LayoutConfig.MATCH_CONTENT);//設置margintextLayoutConfig.setMargins(100, 100, 100, 100);// 將布局配置對象設置給布局對象(為組件添加對應布局的布局屬性)text.setLayoutConfig(textLayoutConfig);// 設置text布局背景為淡紫色// 創(chuàng)建背景元素ShapeElement shapeElementText = new ShapeElement();// 設置淡紫色shapeElementText.setRgbColor(new RgbColor(230, 230, 250));// 將背景設置給布局 設置頁面背景顏色text.setBackground(shapeElementText);// 設置顯示的文本text.setText("Hi there");// 設置文字顏色text.setTextColor(Color.BLACK);//text.setTextColor(new Color(0xFF258293));// 設置文字大小text.setTextSize(100);// 設置對齊方式 , 居中text.setTextAlignment(TextAlignment.CENTER);// 將組件添加到布局中directionalLayout.addComponent(text);//將布局作為根布局添加到視圖樹中super.setUIContent(directionalLayout);}@Overridepublic void onActive() {super.onActive();}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);} }生命周期
Page Ability生命周期
官方文檔:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-page-lifecycle-0000000000029840#ZH-CN_TOPIC_0000001083455837__fig3655123011010
注意
onStart()在整個生命周期過程中僅觸發(fā)一次,而onActive()在每一次從后臺回到前臺的時候都會被調用,所以在開發(fā)中,把只需要加載一次的資源放在onStart()中,把要實時變更的資源放在onActive()中。
開發(fā)者通常需要成對實現(xiàn)onActive()和onInactive(),在onActive()中獲取在onInactive()中被釋放的資源。
AbilitySlice生命周期
AbilitySlice作為Page Ability的組成單元,其生命周期是依托于其所屬Page Ability生命周期的。
AbilitySlice和Page Ability具有相同的生命周期狀態(tài)和同名的回調,當Page Ability生命周期發(fā)生變化時,它的AbilitySlice也會發(fā)生相同的生命周期變化。
此外,AbilitySlice還具有獨立于Page Ability的生命周期變化,這發(fā)生在同一Page Ability中的AbilitySlice之間導航時,此時Page Ability的生命周期狀態(tài)不會改變,AbilitySlice生命周期回調與Page Ability的相應回調類似。當Page Ability被系統(tǒng)銷毀時,其所有已實例化的AbilitySlice將聯(lián)動銷毀,而不僅是處于前臺的AbilitySlice。
生命周期示例
生命周期示例之同一Page跳轉
在LifeCycleAbilitySlice的onStart()中增加按鈕跳轉到LifeCycleSecondAbilitySlice
//生命周期示例之同一Page跳轉Button button = (Button) findComponentById(ResourceTable.Id_button);// 為按鈕設置點擊回調button.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {present(new LifeCycleSecondAbilitySlice(), new Intent());}});LifeCycleSecondAbilitySlice.java的代碼如下:
/*** 生命周期測試AbilitySlice** @author 舒小羽* @date 2021/4/15 0015*/ public class LifeCycleSecondAbilitySlice extends AbilitySlice {private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");@Overrideprotected void onStart(Intent intent) {super.onStart(intent);HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onStart");// 聲明布局 創(chuàng)建相對布局, 傳入當前界面 Ability 對象DependentLayout dependentLayout = new DependentLayout(this);// 創(chuàng)建布局配置對象DependentLayout.LayoutConfig// 構造函數(shù)中傳入寬高設置DependentLayout.LayoutConfig layoutConfig = new DependentLayout.LayoutConfig(DependentLayout.LayoutConfig.MATCH_PARENT,DependentLayout.LayoutConfig.MATCH_PARENT);// 將布局配置對象設置給布局對象dependentLayout.setLayoutConfig(layoutConfig);// 設置布局背景為粉紅色// 創(chuàng)建背景元素ShapeElement shapeElement = new ShapeElement();// 設置粉紅色shapeElement.setRgbColor(new RgbColor(255, 130, 171));// 設置頁面背景顏色(將背景設置給布局)dependentLayout.setBackground(shapeElement);// 創(chuàng)建一個Text文本組件Text text = new Text(this);// 設置文本的布局text.setWidth(MATCH_CONTENT);// 設置顯示的文本text.setText("同一個Page的跳轉");// 設置文字顏色text.setTextColor(Color.BLACK);// 設置文字大小text.setTextSize(100);// 將組件添加到布局中dependentLayout.addComponent(text);//將布局作為根布局添加到視圖樹中super.setUIContent(dependentLayout);}@Overridepublic void onActive() {super.onActive();HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onActive");}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onForeground");}@Overrideprotected void onBackground() {super.onBackground();HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onBackground");}@Overrideprotected void onInactive() {super.onInactive();HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onInactive");}@Overrideprotected void onStop() {super.onStop();HiLog.info(LABEL, "LifeCycleSecondAbilitySlice.onStop");} }運行代碼。。。。。。。。。。。。。。。。。。。。。。。。。
首先啟動LifeCycleAbility的是LifeCycleAbilitySlice,生命周期的調用順序為:
LifeCycleAbility.onStart–>LifeCycleAbilitySlice.onStart–>LifeCycleAbility.onActive–>LifeCycleAbilitySlice.onActive
可以看出AbilitySlice作為Page Ability的組成單元,其生命周期是依托于其所屬Page Ability生命周期的。 AbilitySlice和Page Ability具有相同的生命周期狀態(tài)和同名的回調,當Page Ability生命周期發(fā)生變化時,它的AbilitySlice也會發(fā)生相同的生命周期變化。
當點擊LifeCycleAbilitySlice中的按鈕跳轉到LifeCycleAbility的LifeCycleSecondAbilitySlice,生命周期的調用順序為:
LifeCycleAbilitySlice.onInactive–>LifeCycleSecondAbilitySlice.onStart–>LifeCycleSecondAbilitySlice.onActive–>LifeCycleAbilitySlice.onBackground
當點擊返回按鈕,從LifeCycleSecondAbilitySlice返回到LifeCycleAbilitySlice,生命周期的調用順序為:
LifeCycleSecondAbilitySlice.onInactive–>LifeCycleAbilitySlice.onForeground–>LifeCycleAbilitySlice.onActive–>LifeCycleSecondAbilitySlice.onBackground–>LifeCycleSecondAbilitySlice.onStop
同一Page中的AbilitySlice之間導航,Page的生命周期狀態(tài)不會改變。在這個流程中,MainAbility始終處于活躍狀態(tài)。
當點擊手機Home鍵的時候,生命周期的調用順序為:
LifeCycleAbility.onInactive–>LifeCycleAbilitySlice.onInactive–>LifeCycleAbility.onBackground–>LifeCycleAbilitySlice.onBackground
生命周期示例之不同Page跳轉
在LifeCycleAbilitySlice的onStart()中增加按鈕跳轉到LifeCycleDifferentPageAbility
//生命周期示例之不同Page跳轉Button button1 = (Button) findComponentById(ResourceTable.Id_button1);// 為按鈕設置點擊回調button1.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {Intent intent = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("org.example.harmonypageabilitydemo").withAbilityName(".LifeCycleDifferentPageAbility").build();intent.setOperation(operation);startAbility(intent);}});LifeCycleDifferentPageAbility.java的代碼如下:
public class LifeCycleDifferentPageAbility extends Ability {private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setMainRoute(LifeCycleDifferentPageAbilitySlice.class.getName());HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onStart");}@Overrideprotected void onActive() {super.onActive();HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onActive");}@Overrideprotected void onInactive() {super.onInactive();HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onInactive");}@Overrideprotected void onBackground() {super.onBackground();HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onBackground");}@Overrideprotected void onForeground(Intent intent) {super.onForeground(intent);HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onForeground");}@Overrideprotected void onStop() {super.onStop();HiLog.info(LABEL, "LifeCycleDifferentPageAbility.onStop");} }LifeCycleDifferentPageAbilitySlice.java的代碼如下:
public class LifeCycleDifferentPageAbilitySlice extends AbilitySlice {private static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x00201, "resultValue");@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_life_cycle_different_page);HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onStart");}@Overridepublic void onActive() {super.onActive();HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onActive");}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onForeground");}@Overrideprotected void onBackground() {super.onBackground();HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onBackground");}@Overrideprotected void onInactive() {super.onInactive();HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onInactive");}@Overrideprotected void onStop() {super.onStop();HiLog.info(LABEL, "LifeCycleDifferentPageAbilitySlice.onStop");} }運行代碼。。。。。。。。。。。。。。。。。。。。。。。。。
可以看見,從LifeCycleAbility跳轉到LifeCycleDifferentPageAbility,
LifeCycleAbility和LifeCycleAbilitySlice首先都失去焦點,調用了onInactive,接著,LifeCycleDifferentPageAbility與LifeCycleDifferentPageAbilitySlice啟動,調用了onStart,然后一起進入了前臺,調用了onActive,最后,LifeCycleAbility與LifeCycleAbilitySlice都不可見了,調用了onBackground。
當點擊了返回按鈕后
從LifeCycleDifferentPageAbility回到LifeCycleAbility
先是LifeCycleDifferentPageAbility與LifeCycleDifferentPageAbilitySlice失去焦點觸發(fā)onInactive,其次是LifeCycleAbility與LifeCycleAbilitySlice重新進入可見觸發(fā)onForeground,再是LifeCycleAbility與LifeCycleAbilitySlice進入前臺觸發(fā)onActive,然后是LifeCycleDifferentPageAbility與LifeCycleDifferentPageAbilitySlice不可見觸發(fā)onBackground,最后LifeCycleDifferentPageAbility與LifeCycleDifferentPageAbilitySlice銷毀觸發(fā)onStop。
AbilitySlice間的導航
同一Page內導航(同一Page頁面的AbilitySlice間的導航)
不同Page間導航(不同Page頁面的AbilitySlice間的導航(跨Pgae頁面))
AbilitySlice路由配置
雖然一個Page Ability可以由一個或多個AbilitySlice構成,但是Page進入前臺時界面默認只展示一個AbilitySlice。默認展示的AbilitySlice是通過setMainRoute()方法來指定的。
如果需要更改默認展示的AbilitySlice,可以通過addActionRoute() 方法為此AbilitySlice配置一條路由規(guī)則,當其他Page實例期望導航到此AbilitySlice時,可以在Intent中指定Action。配置了新的路由規(guī)則后,需要在配置文件中將其聲明,否則會找不到。
setMainRoute()方法與addActionRoute()方法使用示例如下:
就是說,"action.second"這個action值匹配的是SecondAbilitySlice這個slice,當需要跳轉到SecondAbilitySlice這個slice的時候,通過指定"action.second"這個action值跳轉到slice。
在配置文件中聲明配置的新的路由規(guī)則示例如下:
同一Page內導航
跳轉不攜帶數(shù)據(jù)
Button button = (Button) findComponentById(ResourceTable.Id_button);// 為按鈕設置點擊回調button.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {//第一種導航方式,跳轉到同一page內不攜帶數(shù)據(jù)//參數(shù)1:需要導航去的頁面,參數(shù)2:Intent對象present(new SamePageSlice(), new Intent());}});跳轉并攜帶數(shù)據(jù)
Button button2 = (Button) findComponentById(ResourceTable.Id_button2);// 為按鈕設置點擊回調button2.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {//第二種導航方式,跳轉到同一page內并攜帶數(shù)據(jù)Intent intent1 = new Intent();intent1.setParam("name", "yu");present(new SamePageSlice(), intent1);}});接收攜帶的數(shù)據(jù)(如果攜帶了參數(shù)跳轉,如何獲取到傳遞的參數(shù)呢?)
Intent作為處理請求的對象,會在相應的回調方法中接收請求方傳遞的Intent對象,導航的目標可以在其onStart()回調的參數(shù)中獲得Intent對象。
需要跳轉過去的Slice的onStart()方法的參數(shù)就是一個Intent,因此可以直接通過此Intent去獲取傳遞過去的參數(shù)。
跳轉并返回數(shù)據(jù)
如果開發(fā)者希望在用戶從導航目標AbilitySlice返回時,能夠獲得其返回結果,則應當使用presentForResult()實現(xiàn)導航。用戶從導航目標AbilitySlice返回時,系統(tǒng)將回調onResult()來接收和處理返回結果,開發(fā)者需要重寫該方法。
text = (Text) findComponentById(ResourceTable.Id_text);Button button3 = (Button) findComponentById(ResourceTable.Id_button3);// 為按鈕設置點擊回調button3.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {//第三種導航方式,跳轉到同一page內并返回數(shù)據(jù)//參數(shù)1:需要導航去的頁面,參數(shù)2:Intent對象,參數(shù)3:請求碼presentForResult(new SamePageSlice(), new Intent(), 0);}});//第三種導航方式,跳轉到同一page內并返回數(shù)據(jù)//接收返回的數(shù)據(jù)@Overrideprotected void onResult(int requestCode, Intent resultIntent) {super.onResult(requestCode, resultIntent);//接收requestCode == 0的返回的數(shù)據(jù)if (requestCode == 0) {int id = resultIntent.getIntParam("ID", -1);//-1為默認值,如果沒有傳回id的話text.setText("回傳的數(shù)據(jù) id=" + id);}}返回數(shù)據(jù)
//第三種導航方式,跳轉到同一page內并返回數(shù)據(jù)//返回數(shù)據(jù)(按返回鍵時有效)Intent intent1 = new Intent();intent1.setParam("ID", 123);setResult(intent1);//自動返回上一頁//terminate();注:
第二種和第三種導航方式可以結合成跳轉到同一page內攜帶數(shù)據(jù)并返回數(shù)據(jù)
不同Page間導航
不同Page中的AbilitySlice相互不可見,所以不能通過present()和presentForResult()方法直接導航。AbilitySlice作為Page的內部單元,以Action的形式向外暴露,因此可以通過配置Intent的Action導航到目標AbilitySlice。
Page間的導航可以使用startAbility()或startAbilityForResult()方法,獲得返回結果的回調為onAbilityResult()。在Ability中調用setResult()可以設置返回結果。
根據(jù)Ability的全稱啟動應用
Button button5 = (Button) findComponentById(ResourceTable.Id_button5);button5.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {//根據(jù)Ability的全稱啟動應用,通過Intent來跳轉Intent intent1 = new Intent();//指定待啟動FA的bundleName和abilityName//通過Intent中的OperationBuilder類構造operation對象//指定設備標識(空串表示當前設備)、應用包名、Ability名稱Operation operation = new Intent.OperationBuilder()//設備id(空串表示當前設備).withDeviceId("")//應用的包名 表示包描述。//如果在Intent中同時指定了BundleName和AbilityName,則Intent可以直接匹配到指定的Ability。//如果未同時指定BundleName和AbilityName,則根據(jù)Operation中的其他屬性來啟動應用。.withBundleName("org.example.harmonypageabilitydemo")//跳轉目標的路徑名 通常是包名+類名 或者 .+類名//表示待啟動的Ability名稱。.withAbilityName("org.example.harmonypageabilitydemo.SecondAbility")//.withAbilityName(".SecondAbility").build();//設置操作方式 把operation設置到intent中intent1.setOperation(operation);//通過AbilitySlice的startAbility接口實現(xiàn)啟動另一個頁面startAbility(intent1);//導航的目標Ability可以在其onStart()回調的參數(shù)中獲得Intent對象}});根據(jù)Operation的其他屬性啟動應用
也就是指定另一個page中的AbilitySlice的action值
withAction的值"action.second"已經在前節(jié)的AbilitySlice路由配置用配置過了。
Intent
提到頁面跳轉,就不得不提Intent
官方文檔:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-intent-0000000000038799
Intent是對象之間傳遞信息的載體。例如,當一個Ability需要啟動另一個Ability時,或者一個AbilitySlice需要導航到另一個AbilitySlice時,可以通過Intent指定啟動的目標同時攜帶相關數(shù)據(jù)。
總結
以上是生活随笔為你收集整理的鸿蒙Ability(一):Feature Ability的Page Ability模板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nuxt之Meta标签关键字描述之des
- 下一篇: IT门户的电子产品报价不再准确