1. 程式人生 > >Tasks and Back Stack(任務和返回棧)

Tasks and Back Stack(任務和返回棧)

以下是講解activity的任務和返回棧,從android開發文件中翻譯而來。

一個app通常都包含多個activities,每個activity 的設計都是基於使用者可以執行特定行為,使用者也可以開啟其他activities。比如一個email app 可能有一個展示新郵件的activity ,當用戶選擇一封郵件的時候,就開啟了一個新的activity 來展示該郵件。
一個activity甚至可以開啟在其他app上的activities 。比如:你可以定義一個intent 來執行“send”動作,intent中可以包含data,如郵件地址,內容。其他app上的activity 申明瞭自己能夠處理這種itent的就會被開啟。在這種情況下,intent 就是傳送郵件,emial app 中的activity 開啟。(如果有多個activities 能匹配同一個intent的話,那麼這個系統就會讓使用者選擇其中一個)。當郵件被髮送時,你的activity 獲取了焦點,並且看上去email activity 是你app的一部分。儘管activities 可能來自於不同的app,但是Android 通過把這些activities 放在同一個棧中,保證了使用者的無縫體驗。
一個任務就是當用戶在執行某些操作時,需要和一系列activities 互動,將這些activities 放置在一個集合中,就形成了棧。activities 是在返回棧中被管理,每個activity 都是按照順序被開啟的。
裝置的 Home screen(主介面) 就是大多數任務開啟的地方。當用戶觸控app啟動項的圖示,這個app的任務就跑到前臺來了。如果這個app沒有任務(這個app最近沒有被使用),那麼一個新的任務就會創建出來,main activity 會作為任務中的root activity 被開啟。
當前activity A 開啟了另外一個activity B,新開啟的activity B就會被推到棧頂獲取焦點。之前的activity A 仍然在棧中,但是是stop狀態。當一個activity stop後,系統保留與使用者互動的當前狀態。當用戶按了後退鍵,當前activity 就會從棧頂彈出(activity 被銷燬),之前的activity 重新獲取焦點(之前的UI狀態會被恢復)。在棧中的activities 不會被重新排列,只有進棧或是彈棧—–有當前activity 開啟的時候,會進棧,當用戶按下後退鍵就會彈棧。所以返回棧就是按照“後進先出”(last in, first out)的原則來執行。圖一展示了在每個時間點上,activities 和返回棧的程序。展示了每個在任務中的新的activity 是怎樣將activity 新增到任務棧中的。當用戶按下後退鍵,當前activity 被銷燬,之前的activity 恢復獲取焦點。

這裡寫圖片描述

如果使用者繼續按後退鍵,那麼每個存在棧中的activity 都會被依次彈出,直至使用者返回到主介面(或是任務開啟的時候,任何一個正在執行的activity )。當所有的activities 都被從返回棧中移除,棧就不再存在。
任務是一個內聚單元,當用戶開啟一個新的任務或是通過Home button 返回到主介面的時候,之前的任務轉移到“後臺”。在後臺,所有的activities 都是stop狀態,但是任務的返回棧仍然保持不變—這個任務僅僅是當其他任務開啟的時候它失去了焦點,如下圖所示。一個任務也可以返回到前臺,因此使用者可以接著之前的繼續互動。比如,當前Task A 在它的棧中有3個activities —-2個在當前activity的後面。使用者按下Home button,就從app launcher中啟動一個新的app.當出現主介面,Task A執行在後臺了。當新的app開啟時,系統會為app 開啟一個新的Task B, 裝載自己的activities。當互動之後,使用者又返回到主介面,並且又選擇了當初開啟Task A的app。現在,Task A來到前臺—棧中的3個activities 還是完整不變的,並且在棧頂的activity 獲取焦點。這時候,使用者可以通過返回到主介面,選擇app圖示開啟這個任務來跳轉到Task B .

這裡寫圖片描述

許多tasks 能夠立刻被安排到後臺。然而,如果使用者在同一時間在後臺執行許多tasks 的話,系統為了回收記憶體,可能會銷燬一些後臺的activities ,這會導致activity 狀態丟失。
由於在返回棧的activities 不會被重新排列,如果app允許使用者從眾多的activity中開啟一個特定的activity,一個新的例項就會被建立並且進棧(而不是把之前的activity 例項拿來放在棧頂)。因此,你的app中的一個activity 有可能被例項化許多次,正如圖3所展示的。在這種情況下,如果使用者用按後退鍵一步一步返回,每個activity 例項會按照順序被依次開啟。然而,如果你不希望activity 被例項化許多次,你也可以做修改。以下會講解如何管理Tasks。

這裡寫圖片描述

以下總結的是activities 和tasks預設的行為方式:
  • 當Activity A 啟動Activity B,Activity A 就會stop,但是仍會保持它的狀態(比如滾動的位置,輸入表格中的文字)。如果使用者在Activity B時按下了後退鍵,Activity A 就會帶著之前的狀態恢復過來。
    -
  • 當用戶按下Home button,就會離開這個task 。當前的activity stop的時候,task 就會在後臺執行。系統會保持每個task中activity 的狀態。如果使用者稍後通過點選app啟動圖示來恢復task ,task 就會執行在前臺,恢復在棧頂的activity 。
    -
  • 如果使用者按下Back button,當前activity 彈棧並被銷燬。之前在棧中的activity 就會恢復。當activity 被銷燬,系統就不會保留activity 的狀態。
    -
  • Activities 可以被例項化許多次,甚至在不同的tasks中也可以。
管理任務:Android 管理tasks 和back stack的方式是:把許多已啟動的activities 以一定的順序放在同一個task 中,並遵循”last in, first out”.則對於大多數app來說是行之有效的,你沒有必要擔憂activities 是怎樣與tasks 關聯,或是怎樣在back stack 中存在。然而,你有可能希望app上的一個activity 在開啟的時候,就開啟一個新的task (而不是執行在當前的task);或者當你開啟一個activity時,你希望把已經存在的activity例項拿來而不是創造一個新的例項放在back stack的棧頂;或是當你用遺留下的task,你希望清空back stack 中除了root activity 的所有activities 。通過manifest activity的屬性、傳遞帶有flags 的Intent來startActivity(),你還可以做的更多。
注意:大多數的app 不應該干擾activities 和tasks預設的行為。如果你認為有必要修改activity 的預設行為,確保在啟動的時候測試activity 的可用性。當用back button 導航一步一步返回到此activity ,或是其他activities返回到此activity 時候,也測試它的可用性。也對和使用者期望的習慣相沖突的導航行為做測試。
定義啟動模式:啟動模式允許使用者定義一個新的activity 例項是怎樣和當前task相關聯。你可以用以下2種方式來定義:
  • 用manifest 配置
  • 用Intent flags
如此,如果Activity A 開啟Activity B,Activity B可以在它的manifest 申明自己的啟動模式。Activity A同樣也可以要求Activity B應該用怎樣的啟動模式。如果Activity A 和Activity B 都定義了Activity B的啟動模式,那麼 Activity A的優先權高於Activity B
注意:一些啟動模式有可能對manifest 檔案有效,對帶有flags 的意圖沒效。同樣,一些啟動模式有可能對不能在manifest中申明的、帶有flags 的意圖有效。
使用manifest 檔案:啟動模式定義了一個activity 應該怎樣在任務中被啟動。啟動模式有4種:
  • ”standard“(預設的啟動模式)。當一個activity 開啟的時候,系統就會在task 中建立一個新的例項。這個activity 能夠被例項化許多次,每個例項都屬於不同的tasks,一個task 可以有許多的例項。
  • ”singleTop“:如果一個activity的例項已經在當前task頂部,系統將通過呼叫onNewIntent() 方法來將意圖傳遞給這個activity例項,而不是通過建立一個新的activity例項。這個activity也可以被例項化許多次,每個例項都可以屬於不同的tasks,一個task 可以有許多的例項(但是僅僅是這個activity 在當前back stack 的頂部,而不是已經就存在的activity)例如,假定一個任務的back stack 包括root activity A ,帶有activities B, C,D. D在頂部。即棧中排列順序是:A-B-C-D。一個intent 傳遞給activity D。如果D是預設的”standard“啟動模式,一個新的例項就會被創建出來,stack 中的排列就變為: A-B-C-D-D。然而,如果D的模式是singleTop,已經存在的例項activity D通過onNewIntent()收到intent 。因為D在棧的頂部,所以棧中的順序還是:A-B-C-D。如果有個intent 傳遞給B,那麼B的一個新的例項就會被增加到棧中。注意:當一個activity 新的例項被建立的時候,使用者可以按 Back button 返回到之前的
    activity,但是當由已經存在的activity 例項來處理新的intent時,在新的intent 沒有通過onNewIntent()傳遞過來的時候,使用者不能按Back button返回到之前的activity 狀態。
  • ”singleTask“:系統建立一個新的task 並在新的task根部例項化activity 。然而,如果一個activity 的例項已經在另外一個獨立的task中存在,系統就會把通過呼叫onNewIntent()方法將intent 傳遞給已經存在的activity 例項,而不是建立一個新的例項。一次僅僅只有一個activity 的例項能存在。注意:儘管activity 是在新的task中開啟的,Back button 仍然能讓使用者返回到之前的activity。
  • ”singleInstance“:和singleTask一樣,除了系統不會在已經有了activities 例項的task中啟動任何的activities 了。這個activity 經常是單一的,並起task中只有它一個成員。任何是這種啟動模式的activities 能夠在一個獨立的task中開啟。
另外一個例子就是:Android 瀏覽器申明瞭網頁瀏覽的activity 應該經常在自己的task中開啟—-在mainfest中定義了singleTask 的啟動模式。這意味著如果你的app傳送了一個開啟Android 瀏覽器的intent ,那麼網頁瀏覽的activity 不會和你的app在同一個task中。相反,要麼會為瀏覽器開啟一個新的task ,要麼如果Browser 已經有一個任務在後臺執行,那麼這個task 就會被帶到前臺來處理新的intent。
不管一個activity 是在新的task 中開啟或是被在相同的task 中的activity 開啟,Back button經常能夠使得使用者返回到之前的activity。然而,如果你特別指定了一個activity 是singleTask 啟動模式,如果在後臺的task中已經存在了這個activity 例項,那麼整個task 就會被帶到前臺。這時,back stack包括了task 帶來的所有activities ,並在棧的頂部。用圖4說明這種情形:

這裡寫圖片描述

注意:你在manifest中設定activity 的啟動模式有可能會被intent 中的flags 重寫。
使用Intent flags:當開啟一個activity,在用intent來startActivity()時候,可以在這個intent 中增加flags 來修改activity的預設啟動模式。你可以用來修改activity預設啟動模式的flags有:
  • FLAG_ACTIVITY_NEW_TASK: 在新的task中開啟activity.如果你要開的這個activity的task已經正在執行,那麼這個task 就會被帶到前臺,並恢復之前的狀態。Activity在onNewIntent()接收新的intent 。這和之前討論的singleTask 模式相同。

  • FLAG_ACTIVITY_SINGLE_TOP:如果當前的activity 已經開啟了(在back stack的頂部),那麼已經存在的例項就會呼叫onNewIntent(),而不是建立這個activity的新的例項。這和singleTop模式相同。

  • FLAG_ACTIVITY_CLEAR_TOP:經常性和FLAG_ACTIVITY_NEW_TASK結合使用。當一起使用時,flags在另外的task 中定位已經存在的activity 並將它放在能夠響應intent的地方。

注意:如果一個activity 的啟動模式被指定為standard。這個activity 也會從stack 中移除,一個新的例項就會替代它處理即將到來的intent。這是由於當啟動模式是standard時,會為新的intent 建立新的例項。
清理 back stack:如果使用者離開任務有很長一段時間了,那麼系統就會清理這個task 中所有的activities ,除了root activity。當用戶又返回到task 時,僅僅只能恢復root activity。系統之所以這樣做是由於當過了很長一段時間後,使用者極有可能已經放棄了他們之前所做的,重新開始做一些新的事情。你可以用以下屬性來修改上述行為:
  • alwaysRetainTaskState:如果將task中root activity的這個屬性值設定為真,預設的模式就不會發生了。在很長一段時間後,這個task還是會保留裡面的所有activities 。

  • clearTaskOnLaunch:如果將task中root activity的這個屬性值設定為真,無論何時使用者離開和返回task,都會為root activity清理stack 。換言之,就是和alwaysRetainTaskState相反。使用者經常會返回到activity的初始狀態,儘管他只離開了一小會兒。

  • finishOnTaskLaunch:這個屬性和clearTaskOnLaunch很像,但是它只作用於單一的activity上,不在整個task中。它也可以引起任何的activity 包括 root activity的銷燬。當屬性值設定為真時,只有在當前的會話中,activity 還是task 的一部分。如果使用者離開再返回,就不再是當前的了。

開啟 task:

你可以給一個activity設定 intent filter action :”android.intent.action.MAIN”,category:android.intent.category.LAUNCHER作為開啟一個task 的入口。例如:

這裡寫圖片描述

這種intent filter 會使得這個activity 的icon 和label 在app被啟動的時候展示出來,這給了使用者一個方法來啟動這個activity,返回到這個task 。
第二個能力非常重要:使用者必須能夠離開一個task 並使用了launcher後,能返回到這個task。因此,這裡有2種模式能夠使activities 經常在一個task中初始化。當activity 有ACTION_MAIN 和CATEGORY_LAUNCHER 的intent filter時,應該使用singleTask 和singleInstance 。想象一下,如果這個intent filter 消失不見了:一個intent 開啟了singleTask activity,初始化一個新的task,並且使用者花了一些時間工作在task上。使用者然後按下Home button,那麼這個task 被轉到後臺並不可見。現在使用者卻沒有辦法返回到這個task了。因為它沒有這個launcher。所以對於上述,如果你不希望使用者能夠返回到activity,那麼就把finishOnTaskLaunch屬性值設為true.

相關推薦

Tasks and Back Stack(任務返回)

以下是講解activity的任務和返回棧,從android開發文件中翻譯而來。 一個app通常都包含多個activities,每個activity 的設計都是基於使用者可以執行特定行為,使用者也可以開啟其他activities。比如一個email app

安卓四大元件 之 Activity 之 任務回收Tasks and Back Stack

本文摘要 |---Saving Activity State   |---Managing Tasks     |---Defining launch modes     |---Handling affinities     |---Clearing the back s

Android總結 - Activity任務返回、儲存Activity的狀態

任務和返回棧   一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的元件。另外,Activity之間還應該是可以相互啟動的。比如,一個郵件應用中可能會包含一個用於展示郵件列表的Activity,而當用戶點選了其中某

Activity任務返回、儲存Activity的狀態

任務和返回棧   一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的元件。另外,Activity之間還應該是可以相互啟動的。比如,一個郵件應用中可能會包含一個用於展示郵件列表的Activity

Android官方文件—APP元件(Activities)(Tasks and Back Stack

任務和回退堆疊 應用程式通常包含多個Activity。每個Activity都應圍繞使用者可以執行的特定操作進行設計,並可以啟動其他Activity。例如,電子郵件應用程式可能有一個Activity來顯示新訊息列表。當用戶選擇Activity時,將開啟一個新Activity以

Android任務返回完全解析,細數那些你所不知道的細節

本篇文章主要內容來自於Android Doc,我翻譯之後又做了些加工,英文好的朋友也可以直接去讀原文。任務和返回棧一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的元件。另外,Activity之

Activity之任務返回

   一個應用程式中會有多個activity,每個activity一般都有自己獨立的功能。我們可以用activity啟動自己應用中的另一個activity。例如:從一個數據列表介面,跳轉到一個數據詳情介面。也可以用我們的activity去開啟其他應用的activ

Android 任務返回

任務和返回棧 一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的元件。另外,Activity之間還應該是可以相互啟動的。比如,一個郵件應用中可能會包含一個用於展示郵件列表的Activity

【轉】Tasks and Back Stack

Tasks and Back Stack 一個應用通常包括多個 activity。每個 activity應用設計為圍繞針對執行使用者特定的行為和可以啟動其它 activity。 一個 Activity也可以啟動別個應用的 Activity。當別的應用完成,你的應用會重新啟用

Android任務返回簡單總結

       任務是指在執行特定作業時與使用者互動的一系列 Activity。 這些 Activity 按照各自的開啟順序排列在堆疊(即返回棧)中。一般情況下我們可以認為一個應用就是一個任務,並且這個應用啟動的所有Activity會按照開啟的順序放入堆疊中

面試二:Android任務返回

本篇文章主要內容來自於Android Doc,我翻譯之後又做了些加工,英文好的朋友也可以直接去讀原文。 任務和返回棧 一個應用程式當中通常都會包含很多個Activity,每個Activity都應該設計成為一個具有特定的功能,並且可以讓使用者進行操作的元件。另外,

Stack:刪除並返回頂元素?

在C++中,stack提供了刪除棧頂元素的演算法 stack<int>stk; stk.pop(); 但是有時候,我們希望在刪除的同時能夠知道這個棧頂元素是什麼,而pop()是不能返回棧頂元素的!因此,我們應如下辦法: stack<int>stk; int s

的置空入,出返回頂元素操作

#include "stdio.h" #include "stdlib.h" #define N sizeof(struct stack) typedef struct stack{int data;struct stack *next; }*pstack; //置空鏈棧

順序的置空入返回頂元素

#include "stdio.h" #include "stdlib.h" #define MAXSIZE 100 #define OK 1 #define FALSE 0 //順序棧結構體 typedef struct stack{int data[MAXSIZE];i

記憶體分佈空間---Memory Layout And The Stack

記憶體分佈和棧空間 Memory Layout And The Stack 原作者:Peter Jay Salzman 譯者:劉瀚文 導語 想要快速的學習使用GDB,你必須理解frames資料幀的含義,資料幀又叫做堆疊幀,因為堆疊就是由資料幀構

C# 編程中的堆Stack隊列(Queue)

的區別 bottom seq 序表 gin 數組 src 優秀 順序隊列 一、什麽是堆?(Heap) 堆是無序的,是一片不連續的內存域,由用戶自己來控制和釋放,如果用戶自己不釋放的話,當內存達到一定的特定值時,通過垃圾回收器(GC)來回收。 是程序運行期

java集合框架:淺談如何使用LInkedList實現隊列(Queue)(Stack)

ets pop pri ring uname tac print str sys Java中的LinkedList?是采用雙向循環列表實現的。利用LinkedList?可以實現棧(stack)、隊列(queue) 下面寫兩個例子學生類:int stuId; public i

順序stack

順序棧和鏈棧(stack)   棧的定義:它是一種運算受限的線性表。其限制是僅允許在表的一端進行插入和刪除運算。這一端被稱為棧頂,相對地,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退

Flink入門教程--Jobs and Scheduling(任務排程)

該文件簡單描述了Flink是如何排程Job的,以及如何在JobManager上表現並跟蹤Job狀態。 排程 Flink通過任務槽(Task Slot)定義執行資源,每個TaskManager都有一或多個任務槽,每個任務槽都可以執行一個並行任務流,一個

C++基礎:C++標準庫之stack佇列(queue)

在C++標準庫(STL)中,實現了棧和佇列,方便使用,並提供了若干方法。以下作簡要介紹。 1、棧(stack)說明及舉例: 使用棧,要先包含標頭檔案 : #include<stack> 定義棧,以如下形式實現: stack<Type> s; 其中Ty