喜聞樂見-Android LaunchMode

来源:https://www.cnblogs.com/holy-loki/archive/2018/10/01/9735152.html
-Advertisement-
Play Games

launchMode,通俗點說,就是定義了Activity應該如何被launch的。那麼這幾種模式的區別以及應用場景,會有何不同呢?谷歌是基於什麼原因設計這幾種模式的呢?這幾種模式背後的工作原理是什麼呢? ...


launchMode,通俗點說,就是定義了Activity應該如何被launch的。那麼這幾種模式的區別以及應用場景,會有何不同呢?谷歌是基於什麼原因設計這幾種模式的呢?這幾種模式背後的工作原理是什麼呢?

1. 任務和返回棧

在講解launchMode之前,先說說任務(Task)和返回棧(Back Stack,有些譯作回退棧、任務棧)這兩個概念。

A task is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack—the back stack—in the order in which each activity is opened.

任務是指當完成一個特定的工作時與用戶交互的一系列Activity。這些Activity按照打開的順序存放在一個棧中,即返回棧。

通過定義可以知道,Activity會被按照打開的順序存放。不難猜想,這種存放方式,是為了方便回退操作,也就不難解釋為什麼要用棧去存放。

當用戶點擊啟動app的時候,這個app的返回棧就會跑到前臺,如果這個返回棧不存在的話,就會創建一個。當前Activity啟動另一個Activity的時候,新的Activity就會入棧,在棧頂。如果用戶點擊返回按鈕,當前的Activity就會出棧並銷毀,之前的Activity就會被resume,如果棧為空,就會被銷毀掉。棧中的Activity永遠都不會被重新排序。

返回棧根據是否在前臺,可以分為在前臺顯示的返回棧,和置於後臺的返回棧。其中,置於後臺的返回棧中所有的Activity都處於stop狀態,用戶可以手動的去切換前後臺的返回棧狀態。

當系統記憶體不足時,系統會優先銷毀處於後臺的Activity。那麼問題來了。後臺銷毀Activity的優先順序是怎樣的呢?是將一個返回棧中的Activity都銷毀了過後,再去銷毀另一個,還是說,只是單純的按照Activity來銷毀回收呢?

1.1 任務管理

任務以及返回棧的管理,可以通過一系列的參數設置來進行,包括我們本文講解的launchMode,也是任務管理的一種方式。

1.1.1 taskAffinity

TaskAffinity即任務相關性,標識一個Activity所需要的返回棧的名字。預設情況下是包名。設置了相同taskAffinity屬性的Activity會被放進同一個棧中。一個返回棧的相關性(affinity)是由這個棧的根Activity的相關性(affinity)決定的。

taskAffinity屬性主要與singleTask或allowTaskReparenting結合使用,在其他情況下,這個屬性沒有作用。這是為什麼呢?

1.1.2 allowTaskReparenting

它的主要作用是Activity的遷移,從一個棧遷移到另一個棧,這個遷移跟Activity的taskAffinity有關。

1.1.3 clearTaskOnLaunch

這個屬性用來清除回退棧中除了根Activity的所有Activity,只對根Activity起作用。當設置為true時,每次重新進入app,只會看到根Activity。

1.1.4 finishOnTaskLaunch

這個屬性與clearTaskOnLaunch相反,它是將本Activity移除出去,而不影響其他的Activity。

1.1.5 alwaysRetainTaskState

這個屬性的作用是保存返回棧的狀態,只對根Activity起作用。正常情況下,系統清理一個返回棧,會將根Activity之上的所有Activity都清除掉。設置該屬性後,系統會保存當前的狀態。

2. 啟動模式

啟動模式主要的作用是什麼呢?根據上面對任務及返回棧的介紹,它的作用是定義,一個新的Activity實例如何與當前的任務相關聯。它本身是任務的管理方式。

啟動模式有兩種定義方式,manifest里定義和intent flag的方式。一種是類似配置式的,一種是代碼層面的。可以大致推測,肯定是帶麽層面的優先順序高一些,但是代碼方式劣處就是不啟動Activity就無法設置。Android中這種一般提供動態以及靜態方式的,套路都大致相同,一些區別各種優劣等。

其中manifest設置與intent flag中都包含對方沒有的方式。這也是兩者的一個區別。

2.1 launchMode

此處的launchMode專指Activity的launchMode屬性。其中有四種方式,這四種方式想必大家也都很清楚了,在這裡我不詳細展開了。

2.1.1 standard

最常見的一種模式,Activity的預設模式,每次啟動該模式的Activity,都會被重新創建,可以從屬不同的任務,也可以在一個任務中被創建多次。

它的應用場景特別廣泛, 一般不是特殊需求的話,都會去使用這種模式。

2.1.2 singleTop

如果在當前任務的棧頂,系統會調用Activity的onNewIntent()方法而不是重新創建一個新的實例。當用戶點擊返回鍵時,當前Activity會被出棧,而不是會退到onNewIntent()之前的狀態。

它的應用場景也有一些。例如搜索頁面,每次打開,搜索一些結果,點擊詳情頁面,然後繼續搜索。在比方說,通過通知打開的頁面,如果該頁面存在,則更新,如果不存在,則創建。

2.1.3 singleTask

該模式只允許系統中存在一個該Activity的實例,如果當前實例不存在,則創建,如果已經存在,則將該實例之上的Activity全部出棧,走onNewIntent()。

singleTask適合作為程式入口點,當通過其他方式調用app時候,不會反覆創建主頁面。例如一般情況下的MainActivity,其他app調用的時候。

2.1.4 singleInstance

這種模式與singleTask十分類似,區別在於,持有該Activity的任務中只能包含一個Activity即它本身。

singleInstance適合需要與程式分離開的頁面,例如鬧鐘的響鈴界面,與鬧鐘的設置相分離。再例如系統的撥號界面。

2.2 Intent flags

此處討論的是通過代碼方式進行設置,常見的有如下三種方式。

2.2.1 FLAG_ACTIVITY_NEW_TASK

使用一個新的返回棧來啟動Activity,跟上面討論的singleTask類似

2.2.2 FLAG_ACTIVITY_SINGLE_TOP

跟上面討論的singleTop類似

2.2.3 FLAG_ACTIVITY_CLEAR_TOP

這種方式是上面討論的launchMode中不存在的,它與singleTop的區別是,當已存在該實例了,會將它之上的Activity都出棧。

它經常與FLAG_ACTIVITY_NEW_TASK組合使用,可以達到singleTask的作用。

3. 回到問題

幾種模式的區別以及應用場景,會有何不同呢?

答案見上面關於launchMode

谷歌是基於什麼原因設計這幾種模式的呢?

關於這個問題,我們先倒著來推理,即從使用場景去考慮,一般狀況下,我們打開一個頁面,不在意是否是唯一,這個是最常見的需求,因此有了standard模式,這種也是預設的模式。當我們用搜索頁面,當最頂層是搜索頁面的時候,我不希望再打開一個搜索頁面,於是有了singleTop模式。當從其他App調用我們的app的時候,我只希望只顯示一個主頁面時,於是有了singleTask。關於singleInstance模式,則是希望與當前的頁面分離。

但是,我覺得谷歌並不能列舉出所有的場景,例如,我希望打開一個頁面,記錄當前的路徑,例如a->b->c,這種場景下,四種模式裡面沒有包含。

如果從正面去推導的話,幾種啟動模式是任務及返回棧的管理。根據在棧中的狀態,大致可以分為如下幾類:

  1. 最常見的出棧入棧(standard)
  2. 當前棧中唯一(singleTask)
  3. 全局唯一(singleInstance)
  4. 棧頂唯一(singleTop)

是不是很明晰了,有沒有其他的出現形式?肯定有的,例如棧底唯一,棧中唯一。但是這種方式可以等同於當前棧中唯一啊。

我們是否可以推導出,谷歌是根據唯一性,來將啟動模式分為這幾種呢?intent flags則作為輔助的一些操作,例如部分出棧等等。當然這些也只是我的推測,不一定准確,哈哈。

這幾種模式背後的工作原理是什麼呢?

見任務及返回棧

記憶體回收的方式,是以Activity還是以任務作為基準回收?

目前已知的狀況時,如果返回棧置於後臺,當記憶體不足的時候,如果不設置alwaysRetainTaskState屬性的話,會將除了根Activity的所有Activity銷毀掉。可以確定是以返回棧為基準來進行回收。

taskAffinity屬性為什麼與singleTask一起使用才生效?

可以將Activity的launchMode根據是否在棧中唯一分為兩類

  1. standard、singleTop
  2. singleTask、singleInstance

第一類因為其唯一性,肯定是與taskAffinity不相容的。singleInstance創建的棧中只能包含本身,預設情況下都會單獨創建一個棧,指定與否都會單獨創建,因此設置沒有意義。而singleTask則是當前棧中唯一,適合作為根Activity,創建一個新的棧,這也是為什麼taskAffinity只能對根Activity起作用的緣故。

4. 最後

我寫的內容不一定正確,一些問題的解釋也是根據我看到的資料來推到出來的,例如Activity為什麼會有四種啟動模式,如果大家有準確地答案,希望告知。另外,文中錯誤的地方,也希望指正。

最後,感謝大家的瀏覽,希望對您有所幫助。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、下載git clone clone https://github.com/coreos/prometheus-operator.git或:wget https://github.com/coreos/prometheus-operator/archive/v0.23.0.tar.gz並解壓 (我 ...
  • 【原創,轉載請註明出處】 應屆生小祖參加了個需求分析會回來後跟我說被產品懟了一句: "不就是寫SQL嗎,要那麼久嗎" 我去,欺負我小弟,這我肯定不能忍呀,於是我寫了一篇文章發在了公司的wiki 貼出來給大家看看,省略了一些敏感的內容。當然內部版言辭也會溫和一點,嘻嘻 在哪裡寫SQL? 這個問題高級點 ...
  • 用PowerDesigner比較直觀, 方便管理,修改資料庫,分享 Oracle的逆向工程,和模型圖的顯示設置 Oracle 為32位的,64位的Oracle PowerDesigner新版本支持,但是搞不到破解碼... https://blog.csdn.net/u011781521/articl ...
  • oracle10g以上支持正則表達式的函數主要有下麵四個:1、REGEXP_LIKE :與LIKE的功能相似2、REGEXP_INSTR :與INSTR的功能相似3、REGEXP_SUBSTR :與SUBSTR的功能相似4、REGEXP_REPLACE :與REPLACE的功能相似POSIX 正則表 ...
  • 一. xtrabackup 選項說明 在操作xtrabackup備份與恢復之前,先看下該工具的選項,下麵記錄了xtrabackup二進位文件的部分命令行選項,後期把常用的選項在補上。點擊查看xtrabackup Option 指南 選項名 說明 --apply-log-only 僅在準備備份時,執行 ...
  • like 用法介紹: 1、“_”:匹配單個任意字元 select * from bqh3 where name like '_崔'; 2、“%”:匹配0個或多個任意字元。但有三種情況如下: like %關鍵字:以關鍵字開頭的記錄 like 關鍵字%:以關鍵字結尾的記錄 like %關鍵字% :包含以 ...
  • 本文介紹了熱門的NoSQL資料庫MongoDB的副本集這種分散式架構的一些概念和操作。主要內容包括: MongoDB副本集相關概念 MongoDB副本集環境搭建 MongoDB副本集的讀寫分離 MongoDB副本集的故障轉移 MongoDB副本集的優點 MongoDB副本集的缺點 1.副本集相關概念 ...
  • 本文列舉了項目開發使用Flutter會遇到的問題,以及如何使用Flutter module在現有項目中集成Flutter,並對其原理進行了分析。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...