鴻蒙開發核心之Ability詳解【鴻蒙專題08】

      網友投稿 1276 2025-04-01

      鴻蒙開發核心之Ability詳解


      Ability是應用所具備能力的抽象,也是應用程序的重要組成部分。一個應用可以具備多種能力(即可以包含多個Ability),HarmonyOS支持應用以Ability為單位進行部署。Ability可以分為FA(Feature Ability)和PA(Particle Ability)兩種類型,每種類型為開發者提供了不同的模板,以便實現不同的業務功能。

      FA(Feature Ability) 中文意思是功能能力,支持Page Ability

      Page模板是FA唯一支持的模板,用于提供與用戶交互的能力。一個Page實例可以包含一組相關頁面,每個頁面用一個AbilitySlice實例表示。

      PA(Particle Ability) 這個里面也是支持兩個能力, Service Ability 和 Data Ability 我相信你知道它們的意思,就是服務能力和數據能力。

      Service模板:用于提供后臺運行任務的能力。

      Data模板:用于對外部提供統一的數據訪問抽象。

      例如,新聞APP可以通過一個Page來實現,其中包含了兩個AbilitySlice:一個AbilitySlice用于展示新聞列表,另一個AbilitySlice用于展示新聞詳情。Page和AbilitySlice的關系如圖所示。

      Page與AbilitySlice

      上面的例子大家看懂了沒?一個 Page 可以包含多個 AbilitySlice,但是 Page 進入前臺時界面默認只展示一個AbilitySlice。默認展示的 AbilitySlice 是通過 setMainRoute() 方法來指定的。如果需要更改默認展示的 AbilitySlice,可以通過 addActionRoute() 方法為此 AbilitySlice 配置一條路由規則。

      package com.example.harmonyosdemo; import com.example.harmonyosdemo.slice.MainAbilitySlice; import com.example.harmonyosdemo.slice.SecondAbilitySlice; import ohos.aafwk.ability.Ability; import ohos.aafwk.content.Intent; public class MainAbility extends Ability { @Override public void onStart(Intent intent) { super.onStart(intent); //默認顯示 super.setMainRoute(MainAbilitySlice.class.getName()); //配置路由規則顯示 addActionRoute( "action.second", SecondAbilitySlice.class.getName()); } }

      看圖可能更加容易理解。

      此時,當其他 Page 實例期望導航到此 AbilitySlice 時,可以在 Intent 中指定 Action。addActionRoute() 方法中使用的動作命名,需要在應用配置文件(config.json)中注冊:

      "skills": [ { "entities": [ "entity.system.home" ], "actions": [ "action.system.home", "action.second" ] } ],

      當然在配置文件(config.json)中注冊Ability時,可以通過配置Ability元素中的“type”屬性來指定Ability模板類型,示例如下。

      其中,“type”的取值可以為“page”、“service”或“data”,分別代表 Page 模板、Service 模板、Data 模板。結合下面這個圖來看知道是怎么回事了,type的屬性值取決于你創建Ability是選擇的類型,當然你也可以后面再改。

      { "module": { ... "abilities": [ { ... "type": "page" ... } ] ... } ... }

      一 、Page Ability講解

      Android 中有Activity,Activity有生命周期,現在我們知道的是鴻蒙這個Page Ability是主要負責頁面交互的,同樣的Page Ability也是有生命周期的。

      1. Page Ability 生命周期

      系統管理或用戶操作等行為均會引起Page實例在其生命周期的不同狀態之間進行轉換。Ability類提供的回調機制能夠讓Page及時感知外界變化,從而正確地應對狀態變化(比如釋放資源),這有助于提升應用的性能和穩健性。

      首先來看官方的一張圖

      可以看到周期分別是onStart()、onActive()、onInactive()、onBackground()、onForeground()、onStop()六個,那么接下來我們就詳細了解一下。

      當系統首次創建 Page Ability實例時,觸發該回調。對于一個 Page Ability實例,該回調在其生命周期過程中僅觸發一次,Page Ability在該邏輯后將進入 INACTIVE 狀態。開發者必須重寫該方法,并在此配置默認展示的 AbilitySlice。如下圖所示

      Page會在進入INACTIVE狀態后來到前臺,然后系統調用此回調。Page在此之后進入ACTIVE狀態,該狀態是應用與用戶交互的狀態。Page將保持在此狀態,除非某類事件發生導致Page失去焦點,比如用戶點擊返回鍵或導航到其他Page。當此類事件發生時,會觸發Page回到INACTIVE狀態,系統將調用onInactive()回調。此后,Page可能重新回到ACTIVE狀態,系統將再次調用onActive()回調。因此,開發者通常需要成對實現onActive()和onInactive(),并在onActive()中獲取在onInactive()中被釋放的資源。類似于Android的onResume。

      當Page失去焦點時,系統將調用此回調,此后Page進入INACTIVE狀態。開發者可以在此回調中實現Page失去焦點時應表現的恰當行為。類似于Android的onPause和onStop的集合體。

      如果Page不再對用戶可見,系統將調用此回調通知開發者用戶進行相應的資源釋放,此后Page進入BACKGROUND狀態。開發者應該在此回調中釋放Page不可見時無用的資源,或在此回調中執行較為耗時的狀態保存操作。

      處于BACKGROUND狀態的Page仍然駐留在內存中,當重新回到前臺時(比如用戶重新導航到此Page),系統將先調用onForeground()回調通知開發者,而后Page的生命周期狀態回到INACTIVE狀態。開發者應當在此回調中重新申請在onBackground()中釋放的資源,最后Page的生命周期狀態進一步回到ACTIVE狀態,系統將通過onActive()回調通知開發者用戶。

      系統將要銷毀Page時,將會觸發此回調函數,通知用戶進行系統資源的釋放。銷毀Page的可能原因包括以下幾個方面:

      用戶通過系統管理能力關閉指定Page,例如使用任務管理器關閉Page。

      用戶行為觸發Page的terminateAbility()方法調用,例如使用應用的退出功能。

      配置變更導致系統暫時銷毀Page并重建。

      系統出于資源管理目的,自動觸發對處于BACKGROUND狀態Page的銷毀。

      2. AbilitySlice 生命周期

      說實話一開始創建項目的時候就只有這個MainAbility和HelloWorld以及slice包下的MainAbilitySlice,后來新建了一個SecondAbility,而SecondAbilitySlice是自動生成的,這說明一個問題,它們之間有不可告人的秘密。我們可以一起來看看,

      解釋:AbilitySlice 作為 Page Ability的組成單元,其生命周期是依托于其所屬 Page Ability生命周期的。AbilitySlice 和 Page Ability具有相同的生命周期狀態和同名的回調,當 Page Ability生命周期發生變化時,它的 AbilitySlice 也會發生相同的生命周期變化。此外,AbilitySlice 還具有獨立于 Page Ability的生命周期變化,這發生在同一 Page Ability中的 AbilitySlice 之間導航時,此時 Page Ability的生命周期狀態不會改變。AbilitySlice 生命周期回調與 Page Ability的相應回調類似,因此不再贅述。由于 AbilitySlice 承載具體的頁面,開發者必須重寫 AbilitySlice 的 onStart()回調,并在此方法中通過 setUIContent()方法設置頁面,如下所示:

      Page 與 AbilitySlice 生命周期關聯

      當 AbilitySlice 處于前臺且具有焦點時,其生命周期狀態隨著所屬 Page Ability的生命周期狀態的變化而變化。當一個 Page Ability擁 有多個 AbilitySlice 時,例如:MyAbility 下有 FooAbilitySlice 和 BarAbilitySlice,當前 FooAbilitySlice 處于前臺并獲得焦點,并即將導航到 BarAbilitySlice,在此期間的生命周期狀態變化順序為:

      1.FooAbilitySlice 從 ACTIVE 狀態變為 INACTIVE 狀態。

      2.BarAbilitySlice 則從 INITIAL 狀態首先變為 INACTIVE 狀態,然后變為 ACTIVE 狀態(假定此前 BarAbilitySlice 未曾啟動)。

      3.FooAbilitySlice 從 INACTIVE 狀態變為 BACKGROUND 狀態。對應兩個 slice 的生命周期方法回調順序為:

      FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground() 在整個流程中,MyAbility 始終處于 ACTIVE 狀態。但是,當 Page Ability被系統銷毀時,其所有已 實例化的 AbilitySlice 將聯動銷毀,而不僅是處于前臺的 AbilitySlice。

      鴻蒙開發核心之Ability詳解【鴻蒙專題08】

      二、Service Ability

      Service Ability基本概念

      基于Service模板的Ability(以下簡稱“Service”)主要用于后臺運行任務(如執行音樂播放、文件下載等),但不提供用戶交互界面。Service可由其他應用或Ability啟動,即使用戶切換到其他應用,Service仍將在后臺繼續運行。

      Service是單實例的。在一個設備上,相同的Service只會存在一個實例。如果多個Ability共用這個實例,只有當與Service綁定的所有Ability都退出后,Service才能夠退出。由于Service是在主線程里執行的,因此,如果在Service里面的操作時間過長,開發者必須在Service里創建新的線程來處理(詳見線程間通信),防止造成主線程阻塞,應用程序無響應。

      創建Service

      首先介紹如何創建一個Service。

      創建Ability的子類,實現Service相關的生命周期方法。Service也是一種Ability,Ability為Service提供了以下生命周期方法,開發者可以重寫這些方法,來添加其他Ability請求與Service Ability交互時的處理方法。

      onStart()

      該方法在創建Service的時候調用,用于Service的初始化。在Service的整個生命周期只會調用一次,調用時傳入的Intent應為空。

      onCommand()

      在Service創建完成之后調用,該方法在客戶端每次啟動該Service時都會調用,開發者可以在該方法中做一些調用統計、初始化類的操作。

      onConnect()

      在Ability和Service連接時調用,該方法返回IRemoteObject對象,開發者可以在該回調函數中生成對應Service的IPC通信通道,以便Ability與Service交互。Ability可以多次連接同一個Service,系統會緩存該Service的IPC通信對象,只有第一個客戶端連接Service時,系統才會調用Service的onConnect方法來生成IRemoteObject對象,而后系統會將同一個RemoteObject對象傳遞至其他連接同一個Service的所有客戶端,而無需再次調用onConnect方法。

      onDisconnect()

      在Ability與綁定的Service斷開連接時調用。

      onStop()

      在Service銷毀時調用。Service應通過實現此方法來清理任何資源,如關閉線程、注冊的偵聽器等。

      創建Service的代碼示例如下:

      public class ServiceAbility extends Ability { @Override public void onStart(Intent intent) { super.onStart(intent); } @Override public void onCommand(Intent intent, boolean restart, int startId) { super.onCommand(intent, restart, startId); } @Override public IRemoteObject onConnect(Intent intent) { return super.onConnect(intent); } @Override public void onDisconnect(Intent intent) { super.onDisconnect(intent); } @Override public void onStop() { super.onStop(); } }

      2.注冊Service。

      Service也需要在應用配置文件中進行注冊,注冊類型type需要設置為service。

      { "module": { "abilities": [ { "name": ".ServiceAbility", "type": "service", "visible": true ... } ] ... } ... }

      啟動Service

      介紹通過startAbility()啟動Service以及對應的停止方法。

      啟動Service

      Ability為開發者提供了startAbility()方法來啟動另外一個Ability。因為Service也是Ability的一種,開發者同樣可以通過將Intent傳遞給該方法來啟動Service。不僅支持啟動本地Service,還支持啟動遠程Service。

      開發者可以通過構造包含DeviceId、BundleName與AbilityName的Operation對象來設置目標Service信息。這三個參數的含義如下:

      DeviceId:表示設備ID。如果是本地設備,則可以直接留空;如果是遠程設備,可以通過ohos.distributedschedule.interwork.DeviceManager提供的getDeviceList獲取設備列表,詳見Java API參考。

      BundleName:表示包名稱。

      AbilityName:表示待啟動的Ability名稱。

      啟動本地設備Service的代碼示例如下:

      Intent intent = new Intent(); Operation operation = new Intent.OperationBuilder() .withDeviceId("") .withBundleName("com.domainname.hiworld.himusic") .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility") .build(); intent.setOperation(operation); startAbility(intent);

      啟動遠程設備Service的代碼示例如下:

      Intent intent = new Intent(); Operation operation = new Intent.OperationBuilder() .withDeviceId("") .withBundleName("com.domainname.hiworld.himusic") .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility") .build(); intent.setOperation(operation); startAbility(intent);

      執行上述代碼后,Ability將通過startAbility() 方法來啟動Service。

      如果Service尚未運行,則系統會先調用onStart()來初始化Service,再回調Service的onCommand()方法來啟動Service。

      如果Service正在運行,則系統會直接回調Service的onCommand()方法來啟動Service。

      停止Service

      Service一旦創建就會一直保持在后臺運行,除非必須回收內存資源,否則系統不會停止或銷毀Service。開發者可以在Service中通過terminateAbility()停止本Service或在其他Ability調用stopAbility()來停止Service。

      停止Service同樣支持停止本地設備Service和停止遠程設備Service,使用方法與啟動Service一樣。一旦調用停止Service的方法,系統便會盡快銷毀Service。

      連接Service

      如果Service需要與Page Ability或其他應用的Service Ability進行交互,則須創建用于連接的Connection。Service支持其他Ability通過connectAbility()方法與其進行連接。

      在使用connectAbility()處理回調時,需要傳入目標Service的Intent與IAbilityConnection的實例。IAbilityConnection提供了兩個方法供開發者實現:onAbilityConnectDone()是用來處理連接Service成功的回調,onAbilityDisconnectDone()是用來處理Service異常死亡的回調。

      創建連接Service回調實例的代碼示例如下:

      // 創建連接Service回調實例 private IAbilityConnection connection = new IAbilityConnection() { // 連接到Service的回調 @Override public void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) { // Client側需要定義與Service側相同的IRemoteObject實現類。開發者獲取服務端傳過來IRemoteObject對象,并從中解析出服務端傳過來的信息。 } // Service異常死亡的回調 @Override public void onAbilityDisconnectDone(ElementName elementName, int resultCode) { } };

      連接Service的代碼示例如下:

      // 連接Service Intent intent = new Intent(); Operation operation = new Intent.OperationBuilder() .withDeviceId("deviceId") .withBundleName("com.domainname.hiworld.himusic") .withAbilityName("com.domainname.hiworld.himusic.ServiceAbility") .build(); intent.setOperation(operation); connectAbility(intent, connection);

      同時,Service側也需要在onConnect()時返回IRemoteObject,從而定義與Service進行通信的接口。onConnect()需要返回一個IRemoteObject對象,HarmonyOS提供了IRemoteObject的默認實現,用戶可以通過繼承LocalRemoteObject來創建自定義的實現類。Service側把自身的實例返回給調用側的代碼示例如下:

      // 創建自定義IRemoteObject實現類 private class MyRemoteObject extends LocalRemoteObject { MyRemoteObject(){ } } // 把IRemoteObject返回給客戶端 @Override protected IRemoteObject onConnect(Intent intent) { return new MyRemoteObject(); }

      Service Ability生命周期

      與Page類似,Service也擁有生命周期,如圖1所示。根據調用方法的不同,其生命周期有以下兩種路徑:

      啟動

      Service

      該Service在其他Ability調用startAbility()時創建,然后保持運行。其他Ability通過調用stopAbility()來停止Service,Service停止后,系統會將其銷毀。

      連接

      Service

      該Service在其他Ability調用connectAbility()時創建,客戶端可通過調用disconnectAbility()斷開連接。多個客戶端可以綁定到相同Service,而且當所有綁定全部取消后,系統即會銷毀該Service。

      connectAbility()也可以連接通過startAbility()創建的Service。

      圖1 Service生命周期

      前臺Service

      一般情況下,Service都是在后臺運行的,后臺Service的優先級都是比較低的,當資源不足時,系統有可能回收正在運行的后臺Service。

      在一些場景下(如播放音樂),用戶希望應用能夠一直保持運行,此時就需要使用前臺Service。前臺Service會始終保持正在運行的圖標在系統狀態欄顯示。

      使用前臺Service并不復雜,開發者只需在Service創建的方法里,調用keepBackgroundRunning()將Service與通知綁定。調用keepBackgroundRunning()方法前需要在配置文件中聲明ohos.permission.KEEP_BACKGROUND_RUNNING權限,同時還需要在配置文件中添加對應的backgroundModes參數。在onStop()方法中調用cancelBackgroundRunning()方法可停止前臺Service。

      使用前臺Service的onStart()代碼示例如下:

      // 創建通知,其中1005為NotificationId NotificationRequest request = new NotificationRequest(1005); NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent(); content.setTitle("title").setText("text"); NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content); request.setContent(notificationContent); // 綁定通知,1005為創建通知時傳入的notificationId keepBackgroundRunning(1005, request);

      在配置文件中,“module > abilities”字段下對當前Service做如下配置:

      { "name": ".ServiceAbility", "type": "service", "visible": true, "backgroundModes": ["dataTransfer", "location"] }

      三 、Data Ability

      Data Ability基本概念

      使用Data模板的Ability(以下簡稱“Data”)有助于應用管理其自身和其他應用存儲數據的訪問,并提供與其他應用共享數據的方法。Data既可用于同設備不同應用的數據共享,也支持跨設備不同應用的數據共享。

      數據的存放形式多樣,可以是數據庫,也可以是磁盤上的文件。Data對外提供對數據的增、刪、改、查,以及打開文件等接口,這些接口的具體實現由開發者提供。

      URI介紹

      Data的提供方和使用方都通過URI(Uniform Resource Identifier)來標識一個具體的數據,例如數據庫中的某個表或磁盤上的某個文件。HarmonyOS的URI仍基于URI通用標準,格式如下:

      scheme:協議方案名,固定為“dataability”,代表Data Ability所使用的協議類型。

      authority:設備ID。如果為跨設備場景,則為目標設備的ID;如果為本地設備場景,則不需要填寫。

      path:資源的路徑信息,代表特定資源的位置信息。

      query:查詢參數。

      fragment:可以用于指示要訪問的子資源。

      URI示例:

      跨設備場景:dataability://device_id/com.domainname.dataability.persondata/person/10

      本地設備:dataability:///com.domainname.dataability.persondata/person/10

      說明:本地設備的“device_id”字段為空,因此在“dataability:”后面有三個“/”。

      總結

      說實話寫這一篇文章花費了一番功夫,不斷的瀏覽官網上的文檔然后結合實際來寫,寫的不是很好,請勿見怪,另外就是覺得官網的教程只是一部分,更多的需要開發者自行去探索和發現,正所謂師傅領進門,修行在個人,鴻蒙需要成長,我們開發者同樣也要成長,也許不會前進的路上會很坎坷,但經歷過后就會發現另一番風景,對于鴻蒙,我是初學者,所以更多是以初學者的態度來記錄。而且我學習的重要的途徑就是這樣,一邊學習,一邊記錄,這樣在以后要用到的時候查看自己的筆記就好。最后希望我們大家一起進步。為鴻蒙的發展與宣傳貢獻自己的一份力量。

      參考文檔

      https://aijishu.com/a/1060000000139663#item-1-2

      https://aijishu.com/a/1060000000139663#item-1-4

      Android 小程序

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:我囤的布洛芬,救了發燒的朋友
      下一篇:Excel使用EFFECT函數計算債券的實際年利率
      相關文章
      亚洲av日韩综合一区在线观看| 亚洲色偷偷偷鲁综合| 国产成人亚洲精品狼色在线| 爱情岛亚洲论坛在线观看 | 国产AV无码专区亚洲AVJULIA| 亚洲无码精品浪潮| 亚洲情侣偷拍精品| 久久久久亚洲精品天堂久久久久久| 亚洲成?Ⅴ人在线观看无码| 亚洲国产精品成人久久蜜臀| 朝桐光亚洲专区在线中文字幕| 国产精品久久亚洲一区二区| 婷婷综合缴情亚洲狠狠尤物| 午夜亚洲WWW湿好爽| 日韩亚洲翔田千里在线| 国产亚洲情侣久久精品| 亚洲国产精品自产在线播放| 亚洲五月午夜免费在线视频| 伊人久久精品亚洲午夜| 国产精一品亚洲二区在线播放| 亚洲国产精品无码久久久不卡| 婷婷久久久亚洲欧洲日产国码AV| 亚洲AV人无码激艳猛片| 久久久久亚洲精品日久生情| 亚洲国产精品综合一区在线| 亚洲w码欧洲s码免费| 在线a亚洲老鸭窝天堂av高清| 亚洲欧美成人一区二区三区| 性色av极品无码专区亚洲| 亚洲精品一级无码鲁丝片| 亚洲人成网77777色在线播放| 亚洲国产精品成人精品无码区在线| 亚洲AV无码国产丝袜在线观看| 久久精品国产亚洲AV无码娇色| 亚洲精品国产手机| 在线观看亚洲AV日韩AV| 国产亚洲视频在线播放大全| 国产亚洲精品成人a v小说| 亚洲成亚洲乱码一二三四区软件| 91嫩草私人成人亚洲影院| 亚洲男女一区二区三区|