HarmonyOS學習路之開發篇——Page Ability

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Page Ability","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Page Ability基本概念","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Page與AbilitySlice","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Page模板(以下簡稱“Page”)是FA唯一支持的模板,用於提供與用戶交互的能力。一個Page可以由一個或多個AbilitySlice構成,AbilitySlice是指應用的單個頁面及其控制邏輯的總和。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當一個Page由多個AbilitySlice共同構成時,這些AbilitySlice頁面提供的業務能力應具有高度相關性。例如,新聞瀏覽功能可以通過一個Page來實現,其中包含了兩個AbilitySlice:一個AbilitySlice用於展示新聞列表,另一個AbilitySlice用於展示新聞詳情。Page和AbilitySlice的關係如圖1所示。圖1 Page與AbilitySlice","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a3/a32ded736b277ccedc3ce7064aca1441.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"相比於桌面場景,移動場景下應用之間的交互更爲頻繁。通常,單個應用專注於某個方面的能力開發,當它需要其他能力輔助時,會調用其他應用提供的能力。例如,外賣應用提供了聯繫商家的業務功能入口,當用戶在使用該功能時,會跳轉到通話應用的撥號頁面。與此類似,HarmonyOS支持不同Page之間的跳轉,並可以指定跳轉到目標Page中某個具體的AbilitySlice。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"AbilitySlice路由配置","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"雖然一個Page可以包含多個AbilitySlice,但是Page進入前臺時界面默認只展示一個AbilitySlice。默認展示的AbilitySlice是通過setMainRoute()方法來指定的。如果需要更改默認展示的AbilitySlice,可以通過addActionRoute()方法爲此AbilitySlice配置一條路由規則。此時,當其他Page實例期望導航到此AbilitySlice時,可以在Intent中指定Action,詳見不同Page間導航。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"setMainRoute()方法與addActionRoute()方法的使用示例如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"public class MyAbility extends Ability {\n @Override\n public void onStart(Intent intent) {\n super.onStart(intent);\n // set the main route\n setMainRoute(MainSlice.class.getName());\n\n // set the action route\n addActionRoute(\"action.pay\", PaySlice.class.getName());\n addActionRoute(\"action.scan\", ScanSlice.class.getName());\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"addActionRoute()方法中使用的動作命名,需要在應用配置文件(config.json)中註冊:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"json"},"content":[{"type":"text","text":"{\n \"module\": {\n \"abilities\": [\n {\n \"skills\":[\n {\n \"actions\":[\n \"action.pay\",\n \"action.scan\"\n ]\n }\n ]\n ...\n }\n ]\n ...\n }\n ...\n}\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Page Ability生命週期","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統管理或用戶操作等行爲均會引起Page實例在其生命週期的不同狀態之間進行轉換。Ability類提供的回調機制能夠讓Page及時感知外界變化,從而正確地應對狀態變化(比如釋放資源),這有助於提升應用的性能和穩健性。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Page生命週期回調","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Page生命週期的不同狀態轉換及其對應的回調,如圖1所示。圖1 Page生命週期","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ac/ac3e79df3d3320cc8ef12059100a47f8.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onStart()當系統首次創建Page實例時,觸發該回調。對於一個Page實例,該回調在其生命週期過程中僅觸發一次,Page在該邏輯後將進入INACTIVE狀態。開發者必須重寫該方法,並在此配置默認展示的AbilitySlice。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":" @Override\n public void onStart(Intent intent) {\n super.onStart(intent);\n super.setMainRoute(FooSlice.class.getName());\n }\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onActive()Page會在進入INACTIVE狀態後來到前臺,然後系統調用此回調。Page在此之後進入ACTIVE狀態,該狀態是應用與用戶交互的狀態。Page將保持在此狀態,除非某類事件發生導致Page失去焦點,比如用戶點擊返回鍵或導航到其他Page。當此類事件發生時,會觸發Page回到INACTIVE狀態,系統將調用onInactive()回調。此後,Page可能重新回到ACTIVE狀態,系統將再次調用onActive()回調。因此,開發者通常需要成對實現onActive()和onInactive(),並在onActive()中獲取在onInactive()中被釋放的資源。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onInactive()當Page失去焦點時,系統將調用此回調,此後Page進入INACTIVE狀態。開發者可以在此回調中實現Page失去焦點時應表現的恰當行爲。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onBackground()如果Page不再對用戶可見,系統將調用此回調通知開發者用戶進行相應的資源釋放,此後Page進入BACKGROUND狀態。開發者應該在此回調中釋放Page不可見時無用的資源,或在此回調中執行較爲耗時的狀態保存操作。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onForeground()處於BACKGROUND狀態的Page仍然駐留在內存中,當重新回到前臺時(比如用戶重新導航到此Page),系統將先調用onForeground()回調通知開發者,而後Page的生命週期狀態回到INACTIVE狀態。開發者應當在此回調中重新申請在onBackground()中釋放的資源,最後Page的生命週期狀態進一步回到ACTIVE狀態,系統將通過onActive()回調通知開發者用戶。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"onStop()","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統將要銷燬Page時,將會觸發此回調函數,通知用戶進行系統資源的釋放。銷燬Page的可能原因包括以下幾個方面:","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶通過系統管理能力關閉指定Page,例如使用任務管理器關閉Page。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用戶行爲觸發Page的terminateAbility()方法調用,例如使用應用的退出功能。 配置變更導致系統暫時銷燬Page並重建。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":1,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統出於資源管理目的,自動觸發對處於BACKGROUND狀態Page的銷燬。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"AbilitySlice生命週期","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbilitySlice作爲Page的組成單元,其生命週期是依託於其所屬Page生命週期的。AbilitySlice和Page具有相同的生命週期狀態和同名的回調,當Page生命週期發生變化時,它的AbilitySlice也會發生相同的生命週期變化。此外,AbilitySlice還具有獨立於Page的生命週期變化,這發生在同一Page中的AbilitySlice之間導航時,此時Page的生命週期狀態不會改變。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbilitySlice生命週期回調與Page的相應回調類似,因此不再贅述。由於AbilitySlice承載具體的頁面,開發者必須重寫AbilitySlice的onStart()回調,並在此方法中通過setUIContent()方法設置頁面,如下所示:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Override\nprotected void onStart(Intent intent) {\n super.onStart(intent);\n\n setUIContent(ResourceTable.Layout_main_layout);\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbilitySlice實例創建和管理通常由應用負責,系統僅在特定情況下會創建AbilitySlice實例。例如,通過導航啓動某個AbilitySlice時,是由系統負責實例化;但是在同一個Page中不同的AbilitySlice間導航時則由應用負責實例化。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Page與AbilitySlice生命週期關聯","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當AbilitySlice處於前臺且具有焦點時,其生命週期狀態隨着所屬Page的生命週期狀態的變化而變化。當一個Page擁有多個AbilitySlice時,例如:MyAbility下有FooAbilitySlice和BarAbilitySlice,當前FooAbilitySlice處於前臺並獲得焦點,並即將導航到BarAbilitySlice,在此期間的生命週期狀態變化順序爲:FooAbilitySlice從ACTIVE狀態變爲INACTIVE狀態。BarAbilitySlice則從INITIAL狀態首先變爲INACTIVE狀態,然後變爲ACTIVE狀態(假定此前BarAbilitySlice未曾啓動)。FooAbilitySlice從INACTIVE狀態變爲BACKGROUND狀態。對應兩個slice的生命週期方法回調順序爲:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"FooAbilitySlice.onInactive() --> BarAbilitySlice.onStart() --> BarAbilitySlice.onActive() --> FooAbilitySlice.onBackground()","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在整個流程中,MyAbility始終處於ACTIVE狀態。但是,當Page被系統銷燬時,其所有已實例化的AbilitySlice將聯動銷燬,而不僅是處於前臺的AbilitySlice。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"AbilitySlice間導航","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"同一Page內導航","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當發起導航的AbilitySlice和導航目標的AbilitySlice處於同一個Page時,您可以通過present()方法實現導航。如下代碼片段展示通過點擊按鈕導航到其他AbilitySlice的方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Override\nprotected void onStart(Intent intent) {\n\n ...\n Button button = ...;\n button.setClickedListener(listener -> present(new TargetSlice(), new Intent()));\n ...\n\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果開發者希望在用戶從導航目標AbilitySlice返回時,能夠獲得其返回結果,則應當使用presentForResult()實現導航。用戶從導航目標AbilitySlice返回時,系統將回調onResult()來接收和處理返回結果,開發者需要重寫該方法。返回結果由導航目標AbilitySlice在其生命週期內通過setResult()進行設置。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"@Override\nprotected void onStart(Intent intent) {\n\n ...\n Button button = ...;\n button.setClickedListener(listener -> presentForResult(new TargetSlice(), new Intent(), 0));\n ...\n\n}\n\n@Override\nprotected void onResult(int requestCode, Intent resultIntent) {\n if (requestCode == 0) {\n // Process resultIntent here.\n }\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"系統爲每個Page維護了一個AbilitySlice實例的棧,每個進入前臺的AbilitySlice實例均會入棧。當開發者在調用present()或presentForResult()時指定的AbilitySlice實例已經在棧中存在時,則棧中位於此實例之上的AbilitySlice均會出棧並終止其生命週期。前面的示例代碼中,導航時指定的AbilitySlice實例均是新建的,即便重複執行此代碼(此時作爲導航目標的這些實例是同一個類),也不會導致任何AbilitySlice出棧。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"不同Page間導航","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"AbilitySlice作爲Page的內部單元,以Action的形式對外暴露,因此可以通過配置Intent的Action導航到目標AbilitySlice。Page間的導航可以使用startAbility()或startAbilityForResult()方法,獲得返回結果的回調爲onAbilityResult()。在Ability中調用setResult()可以設置返回結果。詳細用法可參考根據Operation的其他屬性啓動應用中的示例。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"跨設備遷移","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"跨設備遷移(下文簡稱“遷移”)支持將Page在同一用戶的不同設備間遷移,以便支持用戶無縫切換的訴求。以Page從設備A遷移到設備B爲例,遷移動作主要步驟如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"設備A上的Page請求遷移。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"HarmonyOS處理遷移任務,並回調設備A上Page的保存數據方法,用於保存遷移必須的數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"HarmonyOS在設備B上啓動同一個Page,並回調其恢復數據方法。 開發者可以參考以下詳細步驟開發具有遷移功能的Page。","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"實現IAbilityContinuation接口","attrs":{}}]},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"說明一個應用可能包含多個Page,僅需要在支持遷移的Page中通過以下方法實現IAbilityContinuation接口。同時,此Page所包含的所有AbilitySlice也需要實現此接口。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"onStartContinuation()Page請求遷移後,系統首先回調此方法,開發者可以在此回調中決策當前是否可以執行遷移,比如,彈框讓用戶確認是否開始遷移。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"onSaveData()如果onStartContinuation()返回true,則系統回調此方法,開發者在此回調中保存必須傳遞到另外設備上以便恢復Page狀態的數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"onRestoreData()源側設備上Page完成保存數據後,系統在目標側設備上回調此方法,開發者在此回調中接受用於恢復Page狀態的數據。注意,在目標側設備上的Page會重新啓動其生命週期,無論其啓動模式如何配置。且系統回調此方法的時機在onStart()之前。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"onCompleteContinuation()目標側設備上恢復數據一旦完成,系統就會在源側設備上回調Page的此方法,以便通知應用遷移流程已結束。開發者可以在此檢查遷移結果是否成功,並在此處理遷移結束的動作,例如,應用可以在遷移完成後終止自身生命週期。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"onRemoteTerminated()如果開發者使用continueAbilityReversibly()而不是continueAbility(),則此後可以在源側設備上使用reverseContinueAbility()進行回遷。這種場景下,相當於同一個Page(的兩個實例)同時在兩個設備上運行,遷移完成後,如果目標側設備上Page因任何原因終止,則源側Page通過此回調接收終止通知。","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"請求遷移","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"實現IAbilityContinuation的Page可以在其生命週期內,調用continueAbility()或continueAbilityReversibly()請求遷移。兩者的區別是,通過後者發起的遷移此後可以進行回遷。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"try {\n continueAbility();\n} catch (IllegalStateException e) {\n // Maybe another continuation in progress.\n ...\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以Page從設備A遷移到設備B爲例,詳細的流程如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"設備A上的Page請求遷移。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"系統回調設備A上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onStartContinuation()方法,以確認當前是否可以立即遷移。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"如果可以立即遷移,則系統回調設備A上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onSaveData()方法,以便保存遷移後恢復狀態必須的數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"如果保存數據成功,則系統在設備B上啓動同一個Page,並恢復AbilitySlice棧,然後回調IAbilityContinuation.onRestoreData()方法,傳遞此前保存的數據;此後設備B上此Page從onStart()開始其生命週期回調。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"系統回調設備A上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onCompleteContinuation()方法,通知數據恢復成功與否。","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"請求回遷","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用continueAbilityReversibly()請求遷移並完成後,源側設備上已遷移的Page可以發起回遷,以便使用戶活動重新回到此設備。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"java"},"content":[{"type":"text","text":"try {\n reverseContinueAbility();\n} catch (IllegalStateException e) {\n // Maybe another continuation in progress.\n ...\n}\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以Page從設備A遷移到設備B後並請求回遷爲例,詳細的流程如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"設備A上的Page請求回遷。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"系統回調設備B上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onStartContinuation()方法,以確認當前是否可以立即遷移。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"如果可以立即遷移,則系統回調設備B上Page及其AbilitySlice棧中所有AbilitySlice實例的IAbilityContinuation.onSaveData()方法,以便保存回遷後恢復狀態必須的數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"如果保存數據成功,則系統在設備A上Page恢復AbilitySlice棧,然後回調IAbilityContinuation.onRestoreData()方法,傳遞此前保存的數據。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"text","text":"如果數據恢復成功,則系統終止設備B上Page的生命週期。","attrs":{}}]}]}]}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章