<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          HarmonyOS學(xué)習(xí)路之開發(fā)篇—Page Ability

          共 10401字,需瀏覽 21分鐘

           ·

          2021-07-01 22:04

          點(diǎn)擊上方藍(lán)色字體,關(guān)注我們


          1


          Page Ability基本概念


          Page與AbilitySlice


          Page模板(以下簡(jiǎn)稱“Page”)是FA唯一支持的模板,用于提供與用戶交互的能力。一個(gè)Page可以由一個(gè)或多個(gè)AbilitySlice構(gòu)成,AbilitySlice是指應(yīng)用的單個(gè)頁面及其控制邏輯的總和。


          當(dāng)一個(gè)Page由多個(gè)AbilitySlice共同構(gòu)成時(shí),這些AbilitySlice頁面提供的業(yè)務(wù)能力應(yīng)具有高度相關(guān)性。


          例如,新聞瀏覽功能可以通過一個(gè)Page來實(shí)現(xiàn),其中包含了兩個(gè)AbilitySlice:一個(gè)AbilitySlice用于展示新聞列表,另一個(gè)AbilitySlice用于展示新聞詳情。Page和AbilitySlice的關(guān)系如圖1所示。圖1 Page與AbilitySlice

          相比于桌面場(chǎng)景,移動(dòng)場(chǎng)景下應(yīng)用之間的交互更為頻繁。通常,單個(gè)應(yīng)用專注于某個(gè)方面的能力開發(fā),當(dāng)它需要其他能力輔助時(shí),會(huì)調(diào)用其他應(yīng)用提供的能力。例如,外賣應(yīng)用提供了聯(lián)系商家的業(yè)務(wù)功能入口,當(dāng)用戶在使用該功能時(shí),會(huì)跳轉(zhuǎn)到通話應(yīng)用的撥號(hào)頁面。與此類似,HarmonyOS支持不同Page之間的跳轉(zhuǎn),并可以指定跳轉(zhuǎn)到目標(biāo)Page中某個(gè)具體的AbilitySlice。


          AbilitySlice路由配置


          雖然一個(gè)Page可以包含多個(gè)AbilitySlice,但是Page進(jìn)入前臺(tái)時(shí)界面默認(rèn)只展示一個(gè)AbilitySlice。默認(rèn)展示的AbilitySlice是通過setMainRoute()方法來指定的。如果需要更改默認(rèn)展示的AbilitySlice,可以通過addActionRoute()方法為此AbilitySlice配置一條路由規(guī)則。


          此時(shí),當(dāng)其他Page實(shí)例期望導(dǎo)航到此AbilitySlice時(shí),可以在Intent中指定Action,詳見不同Page間導(dǎo)航。


          setMainRoute()方法與addActionRoute()方法的使用示例如下:


          public class MyAbility extends Ability {
              @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  // set the main route
                  setMainRoute(MainSlice.class.getName());

                  // set the action route
                  addActionRoute("action.pay", PaySlice.class.getName());
                  addActionRoute("action.scan", ScanSlice.class.getName());
              }
          }


          addActionRoute()方法中使用的動(dòng)作命名,需要在應(yīng)用配置文件(config.json)中注冊(cè):


          {
              "module": {
                  "abilities": [
                      {
                          "skills":[
                              {
                                  "actions":[
                                      "action.pay",
                                      "action.scan"
                                  ]
                              }
                          ]
                          ...
                      }
                  ]
                  ...
              }
              ...
          }



          2


          Page Ability生命周期



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


          Page生命周期回調(diào)


          Page生命周期的不同狀態(tài)轉(zhuǎn)換及其對(duì)應(yīng)的回調(diào),如圖1所示:


          圖1 Page生命周期


          • onStart() 當(dāng)系統(tǒng)首次創(chuàng)建Page實(shí)例時(shí),觸發(fā)該回調(diào)。對(duì)于一個(gè)Page實(shí)例,該回調(diào)在其生命周期過程中僅觸發(fā)一次,Page在該邏輯后將進(jìn)入INACTIVE狀態(tài)。開發(fā)者必須重寫該方法,并在此配置默認(rèn)展示的AbilitySlice。

           @Override
              public void onStart(Intent intent) {
                  super.onStart(intent);
                  super.setMainRoute(FooSlice.class.getName());
              }


          • onActive() Page會(huì)在進(jìn)入INACTIVE狀態(tài)后來到前臺(tái),然后系統(tǒng)調(diào)用此回調(diào)。Page在此之后進(jìn)入ACTIVE狀態(tài),該狀態(tài)是應(yīng)用與用戶交互的狀態(tài)。Page將保持在此狀態(tài),除非某類事件發(fā)生導(dǎo)致Page失去焦點(diǎn),比如用戶點(diǎn)擊返回鍵或?qū)Ш降狡渌鸓age。當(dāng)此類事件發(fā)生時(shí),會(huì)觸發(fā)Page回到INACTIVE狀態(tài),系統(tǒng)將調(diào)用onInactive()回調(diào)。此后,Page可能重新回到ACTIVE狀態(tài),系統(tǒng)將再次調(diào)用onActive()回調(diào)。因此,開發(fā)者通常需要成對(duì)實(shí)現(xiàn)onActive()和onInactive(),并在onActive()中獲取在onInactive()中被釋放的資源。
          • onInactive() 當(dāng)Page失去焦點(diǎn)時(shí),系統(tǒng)將調(diào)用此回調(diào),此后Page進(jìn)入INACTIVE狀態(tài)。開發(fā)者可以在此回調(diào)中實(shí)現(xiàn)Page失去焦點(diǎn)時(shí)應(yīng)表現(xiàn)的恰當(dāng)行為。
          • onBackground() 如果Page不再對(duì)用戶可見,系統(tǒng)將調(diào)用此回調(diào)通知開發(fā)者用戶進(jìn)行相應(yīng)的資源釋放,此后Page進(jìn)入BACKGROUND狀態(tài)。開發(fā)者應(yīng)該在此回調(diào)中釋放Page不可見時(shí)無用的資源,或在此回調(diào)中執(zhí)行較為耗時(shí)的狀態(tài)保存操作。
          • onForeground() 處于BACKGROUND狀態(tài)的Page仍然駐留在內(nèi)存中,當(dāng)重新回到前臺(tái)時(shí)(比如用戶重新導(dǎo)航到此Page),系統(tǒng)將先調(diào)用onForeground()回調(diào)通知開發(fā)者,而后Page的生命周期狀態(tài)回到INACTIVE狀態(tài)。開發(fā)者應(yīng)當(dāng)在此回調(diào)中重新申請(qǐng)?jiān)趏nBackground()中釋放的資源,最后Page的生命周期狀態(tài)進(jìn)一步回到ACTIVE狀態(tài),系統(tǒng)將通過onActive()回調(diào)通知開發(fā)者用戶。
          • onStop()
            • 系統(tǒng)將要銷毀Page時(shí),將會(huì)觸發(fā)此回調(diào)函數(shù),通知用戶進(jìn)行系統(tǒng)資源的釋放。銷毀Page的可能原因包括以下幾個(gè)方面:
            • 用戶通過系統(tǒng)管理能力關(guān)閉指定Page,例如使用任務(wù)管理器關(guān)閉Page。
            • 用戶行為觸發(fā)Page的terminateAbility()方法調(diào)用,例如使用應(yīng)用的退出功能。配置變更導(dǎo)致系統(tǒng)暫時(shí)銷毀Page并重建。
            • 系統(tǒng)出于資源管理目的,自動(dòng)觸發(fā)對(duì)處于BACKGROUND狀態(tài)Page的銷毀。

          3


          AbilitySlice生命周期



          AbilitySlice作為Page的組成單元,其生命周期是依托于其所屬Page生命周期的。AbilitySlice和Page具有相同的生命周期狀態(tài)和同名的回調(diào),當(dāng)Page生命周期發(fā)生變化時(shí),它的AbilitySlice也會(huì)發(fā)生相同的生命周期變化。此外,AbilitySlice還具有獨(dú)立于Page的生命周期變化,這發(fā)生在同一Page中的AbilitySlice之間導(dǎo)航時(shí),此時(shí)Page的生命周期狀態(tài)不會(huì)改變。


          AbilitySlice生命周期回調(diào)與Page的相應(yīng)回調(diào)類似,因此不再贅述。由于AbilitySlice承載具體的頁面,開發(fā)者必須重寫AbilitySlice的onStart()回調(diào),并在此方法中通過setUIContent()方法設(shè)置頁面,如下所示:


          @Override
          protected void onStart(Intent intent) {
              super.onStart(intent);

              setUIContent(ResourceTable.Layout_main_layout);
          }


          AbilitySlice實(shí)例創(chuàng)建和管理通常由應(yīng)用負(fù)責(zé),系統(tǒng)僅在特定情況下會(huì)創(chuàng)建AbilitySlice實(shí)例。例如,通過導(dǎo)航啟動(dòng)某個(gè)AbilitySlice時(shí),是由系統(tǒng)負(fù)責(zé)實(shí)例化;但是在同一個(gè)Page中不同的AbilitySlice間導(dǎo)航時(shí)則由應(yīng)用負(fù)責(zé)實(shí)例化。


          Page與AbilitySlice生命周期關(guān)聯(lián)


          當(dāng)AbilitySlice處于前臺(tái)且具有焦點(diǎn)時(shí),其生命周期狀態(tài)隨著所屬Page的生命周期狀態(tài)的變化而變化。當(dāng)一個(gè)Page擁有多個(gè)AbilitySlice時(shí),例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,當(dāng)前FooAbilitySlice處于前臺(tái)并獲得焦點(diǎn),并即將導(dǎo)航到BarAbilitySlice,在此期間的生命周期狀態(tài)變化順序?yàn)椋篎ooAbilitySlice從ACTIVE狀態(tài)變?yōu)镮NACTIVE狀態(tài)。


          BarAbilitySlice則從INITIAL狀態(tài)首先變?yōu)镮NACTIVE狀態(tài),然后變?yōu)锳CTIVE狀態(tài)(假定此前BarAbilitySlice未曾啟動(dòng))。FooAbilitySlice從INACTIVE狀態(tài)變?yōu)锽ACKGROUND狀態(tài)。對(duì)應(yīng)兩個(gè)slice的生命周期方法回調(diào)順序?yàn)椋?/p>


          FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground()


          在整個(gè)流程中,MyAbility始終處于ACTIVE狀態(tài)。但是,當(dāng)Page被系統(tǒng)銷毀時(shí),其所有已實(shí)例化的AbilitySlice將聯(lián)動(dòng)銷毀,而不僅是處于前臺(tái)的AbilitySlice。


          4


          AbilitySlice間導(dǎo)航



          同一Page內(nèi)導(dǎo)航


          當(dāng)發(fā)起導(dǎo)航的AbilitySlice和導(dǎo)航目標(biāo)的AbilitySlice處于同一個(gè)Page時(shí),您可以通過present()方法實(shí)現(xiàn)導(dǎo)航。如下代碼片段展示通過點(diǎn)擊按鈕導(dǎo)航到其他AbilitySlice的方法:


          @Override
          protected void onStart(Intent intent) {

              ...
              Button button = ...;
              button.setClickedListener(listener -> present(new TargetSlice(), new Intent()));
              ...

          }


          如果開發(fā)者希望在用戶從導(dǎo)航目標(biāo)AbilitySlice返回時(shí),能夠獲得其返回結(jié)果,則應(yīng)當(dāng)使用presentForResult()實(shí)現(xiàn)導(dǎo)航。用戶從導(dǎo)航目標(biāo)AbilitySlice返回時(shí),系統(tǒng)將回調(diào)onResult()來接收和處理返回結(jié)果,開發(fā)者需要重寫該方法。返回結(jié)果由導(dǎo)航目標(biāo)AbilitySlice在其生命周期內(nèi)通過setResult()進(jìn)行設(shè)置。


          @Override
          protected void onStart(Intent intent) {

              ...
              Button button = ...;
              button.setClickedListener(listener -> presentForResult(new TargetSlice(), new Intent(), 0));
              ...

          }

          @Override
          protected void onResult(int requestCode, Intent resultIntent) {
              if (requestCode == 0) {
                  // Process resultIntent here.
              }
          }


          系統(tǒng)為每個(gè)Page維護(hù)了一個(gè)AbilitySlice實(shí)例的棧,每個(gè)進(jìn)入前臺(tái)的AbilitySlice實(shí)例均會(huì)入棧。當(dāng)開發(fā)者在調(diào)用present()或presentForResult()時(shí)指定的AbilitySlice實(shí)例已經(jīng)在棧中存在時(shí),則棧中位于此實(shí)例之上的AbilitySlice均會(huì)出棧并終止其生命周期。前面的示例代碼中,導(dǎo)航時(shí)指定的AbilitySlice實(shí)例均是新建的,即便重復(fù)執(zhí)行此代碼(此時(shí)作為導(dǎo)航目標(biāo)的這些實(shí)例是同一個(gè)類),也不會(huì)導(dǎo)致任何AbilitySlice出棧。


          不同Page間導(dǎo)航


          AbilitySlice作為Page的內(nèi)部單元,以Action的形式對(duì)外暴露,因此可以通過配置Intent的Action導(dǎo)航到目標(biāo)AbilitySlice。Page間的導(dǎo)航可以使用startAbility()或startAbilityForResult()方法,獲得返回結(jié)果的回調(diào)為onAbilityResult()。在Ability中調(diào)用setResult()可以設(shè)置返回結(jié)果。詳細(xì)用法可參考根據(jù)Operation的其他屬性啟動(dòng)應(yīng)用中的示例。


          5


          跨設(shè)備遷移



          跨設(shè)備遷移(下文簡(jiǎn)稱“遷移”)支持將Page在同一用戶的不同設(shè)備間遷移,以便支持用戶無縫切換的訴求。以Page從設(shè)備A遷移到設(shè)備B為例,遷移動(dòng)作主要步驟如下:


          1. 設(shè)備A上的Page請(qǐng)求遷移。
          2. HarmonyOS處理遷移任務(wù),并回調(diào)設(shè)備A上Page的保存數(shù)據(jù)方法,用于保存遷移必須的數(shù)據(jù)。
          3. HarmonyOS在設(shè)備B上啟動(dòng)同一個(gè)Page,并回調(diào)其恢復(fù)數(shù)據(jù)方法。開發(fā)者可以參考以下詳細(xì)步驟開發(fā)具有遷移功能的Page。

          實(shí)現(xiàn)IAbilityContinuation接口


          說明 一個(gè)應(yīng)用可能包含多個(gè)Page,僅需要在支持遷移的Page中通過以下方法實(shí)現(xiàn)IAbilityContinuation接口。同時(shí),此Page所包含的所有AbilitySlice也需要實(shí)現(xiàn)此接口。

          1. onStartContinuation() Page請(qǐng)求遷移后,系統(tǒng)首先回調(diào)此方法,開發(fā)者可以在此回調(diào)中決策當(dāng)前是否可以執(zhí)行遷移,比如,彈框讓用戶確認(rèn)是否開始遷移。
          2. onSaveData() 如果onStartContinuation()返回true,則系統(tǒng)回調(diào)此方法,開發(fā)者在此回調(diào)中保存必須傳遞到另外設(shè)備上以便恢復(fù)Page狀態(tài)的數(shù)據(jù)。
          3. onRestoreData() 源側(cè)設(shè)備上Page完成保存數(shù)據(jù)后,系統(tǒng)在目標(biāo)側(cè)設(shè)備上回調(diào)此方法,開發(fā)者在此回調(diào)中接受用于恢復(fù)Page狀態(tài)的數(shù)據(jù)。注意,在目標(biāo)側(cè)設(shè)備上的Page會(huì)重新啟動(dòng)其生命周期,無論其啟動(dòng)模式如何配置。且系統(tǒng)回調(diào)此方法的時(shí)機(jī)在onStart()之前。
          4. onCompleteContinuation() 目標(biāo)側(cè)設(shè)備上恢復(fù)數(shù)據(jù)一旦完成,系統(tǒng)就會(huì)在源側(cè)設(shè)備上回調(diào)Page的此方法,以便通知應(yīng)用遷移流程已結(jié)束。開發(fā)者可以在此檢查遷移結(jié)果是否成功,并在此處理遷移結(jié)束的動(dòng)作,例如,應(yīng)用可以在遷移完成后終止自身生命周期。
          5. onRemoteTerminated() 如果開發(fā)者使用continueAbilityReversibly()而不是continueAbility(),則此后可以在源側(cè)設(shè)備上使用reverseContinueAbility()進(jìn)行回遷。這種場(chǎng)景下,相當(dāng)于同一個(gè)Page(的兩個(gè)實(shí)例)同時(shí)在兩個(gè)設(shè)備上運(yùn)行,遷移完成后,如果目標(biāo)側(cè)設(shè)備上Page因任何原因終止,則源側(cè)Page通過此回調(diào)接收終止通知。

          請(qǐng)求遷移


          實(shí)現(xiàn)IAbilityContinuation的Page可以在其生命周期內(nèi),調(diào)用continueAbility()或continueAbilityReversibly()請(qǐng)求遷移。兩者的區(qū)別是,通過后者發(fā)起的遷移此后可以進(jìn)行回遷。


          try {
              continueAbility();
          catch (IllegalStateException e) {
              // Maybe another continuation in progress.
              ...
          }


          以Page從設(shè)備A遷移到設(shè)備B為例,詳細(xì)的流程如下:


          1. 設(shè)備A上的Page請(qǐng)求遷移。
          2. 系統(tǒng)回調(diào)設(shè)備A上Page及其AbilitySlice棧中所有AbilitySlice實(shí)例的IAbilityContinuation.onStartContinuation()方法,以確認(rèn)當(dāng)前是否可以立即遷移。
          3. 如果可以立即遷移,則系統(tǒng)回調(diào)設(shè)備A上Page及其AbilitySlice棧中所有AbilitySlice實(shí)例的IAbilityContinuation.onSaveData()方法,以便保存遷移后恢復(fù)狀態(tài)必須的數(shù)據(jù)。
            如果保存數(shù)據(jù)成功,則系統(tǒng)在設(shè)備B上啟動(dòng)同一個(gè)Page,并恢復(fù)AbilitySlice棧,然后回調(diào)IAbilityContinuation.onRestoreData()方法,傳遞此前保存的數(shù)據(jù);此后設(shè)備B上此Page從onStart()開始其生命周期回調(diào)。
            系統(tǒng)回調(diào)設(shè)備A上Page及其AbilitySlice棧中所有AbilitySlice實(shí)例的IAbilityContinuation.onCompleteContinuation()方法,通知數(shù)據(jù)恢復(fù)成功與否。

          請(qǐng)求回遷


          使用continueAbilityReversibly()請(qǐng)求遷移并完成后,源側(cè)設(shè)備上已遷移的Page可以發(fā)起回遷,以便使用戶活動(dòng)重新回到此設(shè)備。


          try {
              reverseContinueAbility();
          catch (IllegalStateException e) {
              // Maybe another continuation in progress.
              ...
          }


          以Page從設(shè)備A遷移到設(shè)備B后并請(qǐng)求回遷為例,詳細(xì)的流程如下:


          1. 設(shè)備A上的Page請(qǐng)求回遷。
          2. 系統(tǒng)回調(diào)設(shè)備B上Page及其AbilitySlice棧中所有AbilitySlice實(shí)例的IAbilityContinuation.onStartContinuation()方法,以確認(rèn)當(dāng)前是否可以立即遷移。
          3. 如果可以立即遷移,則系統(tǒng)回調(diào)設(shè)備B上Page及其AbilitySlice棧中所有AbilitySlice實(shí)例的IAbilityContinuation.onSaveData()方法,以便保存回遷后恢復(fù)狀態(tài)必須的數(shù)據(jù)。
          4. 如果保存數(shù)據(jù)成功,則系統(tǒng)在設(shè)備A上Page恢復(fù)AbilitySlice棧,然后回調(diào)IAbilityContinuation.onRestoreData()方法,傳遞此前保存的數(shù)據(jù)。
          5. 如果數(shù)據(jù)恢復(fù)成功,則系統(tǒng)終止設(shè)備B上Page的生命周期。


          往期推薦



          點(diǎn)擊閱讀原文,更精彩~
          瀏覽 42
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  高清一区二区三区 | 色导航| 91久久久久久久久久久 | 蜜桃在线码无精品秘 入口九色 | 免费日本黄色电影网站 |