Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android開發之旅:活動與任務

Android開發之旅:活動與任務

編輯:Android開發實例

——堅持就是勝利!關鍵是你能堅持嗎?不能的話,你注定是個失敗者。

引言

關於Android應用程序原理及術語,前面兩篇:

  • Android開發之旅:應用程序基礎及組件
  • Android開發之旅:應用程序基礎及組件(續)

介紹了Android應用程序的進程運行方式:每一個應用程序運行在它自己的Linux進程中。當應用程序中的任何代碼需要執行時,Android將啟動進程;當它不在需要且系統資源被其他應用程序請求時,Android將關閉進程。而且我們還知道了Android應用程序不像別的應用程序那樣(有Main 函數入口點),它沒有單一的程序入口點,但是它必須要有四個組件中的一個或幾個:活動(Activities) 、服務(Services)、廣播接收者(Broadcast receivers) 、內容提供者(Content providers)。且分別介紹它們的作用,及如何激活和關閉它們、如何在清單文件(AndroidManifest.xml)中聲明它們及 Intent過濾器。

在簡單回顧之後,本篇還是繼續介紹Android應用程序原理及術語——活動與任務(Activities and Tasks)。

  • 1、活動與任務概述
  • 2、親和度和新任務(Affinities and new tasks)
  • 3、啟動模式(Launch modes)
  • 4、清除棧(Clearing the stack)
  • 5、啟動任務(Starting tasks)

1、活動與任務概述

如前所述,一個活動(activity)能啟動另一個活動,包括定義在別的應用程序中的活動。再次舉例說明,假設你想讓用戶顯示某地的街道地圖。而且已經有了一個活動能做這個事情(假設這個活動叫做地圖查看器),因此你的活動要做的就是將請求信息放進一個Intent對象,然後將它傳給startActivity()。地圖查看器就啟動並顯示出地圖。當用戶點擊返回按鈕之後,你的活動就會重新出現在屏幕上。

對用戶來說,這個地圖查看器就好像是你的應用程序的活動一樣,雖然它定義在其他的應用程序中且運行在那個應用程序的進程中。Android將這些活動保持在同一個任務task)中以維持用戶的體驗。簡單地講,任務是用戶體驗上的一個“應用程序”,是排成堆棧的一組相關活動。棧底的活動(根活動)是起始活動——一般來講,它是用戶在應用程序啟動器(也稱應用程序列表,下同)中選擇的一個活動。棧頂的活動是正在運行的活動——它關注用戶的行為(操作)。當一個活動啟動另一個,新的活動被壓入棧頂,變為正在運行的活動。前面那個活動保存在棧中。當用戶點擊返回按鈕時,當前活動從棧頂中彈出,且前面那個活動恢復成為正在運行的活動。(關於棧的先進後出特性不要我在這裡講吧!)

棧中包含對象,因此如果一個活動(再次說明:活動是Activity的子類)啟動了多個實例——例如多個地圖查看器,則棧對每個實例有一個獨立的入口。(可以這樣理解:假設有四個活動以這樣的順序排在棧中——A-B-C-D,現在又有一個C的實例,則棧變成A-B-C-D-C,這兩個C的實例是獨立的。)棧中的活動從不會被重新排列,只會被壓入、彈出。這點很好理解,因為活動的調用順序是固定的。

任務是一棧的活動,而不是清單文件中聲明的某個類或元素,因此無法獨立於它的活動為任務賦值。整個任務的值是在棧底活動(根活動)設置的。例如,下節將討論的“任務親和度”,親和度信息就是從任務的根活動中獲取的。

一個任務的所有活動作為一個整體運行。整個任務(整個活動棧)可置於前台或發送到後台。例如,假設當前任務有四個活動在棧中——三個活動在當前活動下面。用戶按下HOME鍵,切換到程序啟動器,並選擇一個新的應用程序(實際上是一個新的任務)。當前任務進入後台,新任務的根活動將顯示。接著,過了一會,用戶回到主屏幕並再次選擇之前的應用程序(之前的任務)。那個任務棧中的所有四個活動都變為前台運行。當用戶按下返回鍵時,不是離開當前任務回到之前任務的根活動。相反,棧頂的活動被移除且棧中的下一個活動將顯示。

上面所描述的是活動和任務的默認行為,但是有方法來改變所有這些行為。活動與任務之間的聯系及任務中活動的行為,是由啟動活動的Intent對象的標志(flags)和清單文件中活動<activity>元素的屬性共同決定的。

在這方面,主要的Intent標志有:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
  • FLAG_ACTIVITY_SINGLE_TOP

主要的<activity>屬性有:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

接下來的小節將討論這些標志和屬性的作用,他們怎麼交互,及使用的注意事項。

2、親和度和新任務(Affinities and new tasks)

默認情況下,一個應用程序的所有活動互相之間都有一個親和度(affinity——也就是說,他們屬於同一個任務的偏好(preference)。然而,也可以通過<activity>元素的taskAffinity屬性為每個活動設置個體親和度。定義在不同應用程序中的活動能夠共享親和度,同一個應用程序中的活動可以分配不一樣的親和度。親和度發揮作用的兩種情況:1)啟動活動的Intent對象包含FLAG_ACTIVITY_NEW_TASK標志時;2)一個活動的allowTaskReparenting屬性為"true"時。

  • FLAG_ACTIVITY_NEW_TASK標志

如前所述,默認情況下,一個新的活動被啟動到調用startActivity()方法的活動所在的任務。它被壓入調用它的活動的棧中。但是,如果傳遞給方法的Intent對象包含FLAG_ACTIVITY_NEW_TASK標志,系統找一個不同的任務容納活動。通常,顧名思義它表示一個新任務。但是,他並非一定如此。如果已經存在一個任務與新活動親和度一樣,該活動將啟動到該任務。如果不是,則啟動一個新任務。

  • allowTaskReparenting屬性

如果一個活動的allowTaskReparenting屬性為"true",它可以從啟動它的任務轉移到與它有親和度並轉到前台運行的任務中。例如,假設一個天氣預報的活動,但選擇城市是一個旅游應用程序的一部分。它與同一個應用程序中的其他活動具有相同的親和度,且允許重新選擇父活動(reparenting)。你的一個活動啟動天氣預報活動,因此他初始是跟你的活動屬於同一個任務。但是,當旅游應用程序切換到前台運行時,天氣預報活動將被重新分配和顯示到該任務。

如果一個.apk文件,從用戶的角度看包含不止一個“應用程序”,你可能要為與他們有關的些活動指定不一樣的親和度。

3、啟動模式(Launch modes)

有四種不同的啟動模式可以分配到<activity>元素的launchMody屬性:

  • "standard"(默認模式)
  • "singleTop "
  • "singleTask"
  • "singleInstance"

這些模式的在以下四方面不同:

  • 哪個任務將持有響應意圖(intent)的活動。對"standard"和"singleTop "模式,是產生意圖的任務(調用startActivity()方法)——除非Intent對象包含FLAG_ACTIVITY_NEW_TASK標志。在那種情況下,像上一節親和度和新任務(Affinities and new tasks)所描述的那樣選擇一個不同的任務。
    相反,"singleTask"和"singleInstance"模式,總是將活動標記為一個任務的根活動。他們定義一個任務,而從不啟動到其他任務。
  • 活動是否可以實例化多次。"standard"或"singleTop "活動可以實例化多次。這些實例可以屬於多個任務,且一個給定任務可以包含同一個活動的多個實例。
    相反,"singleTask"和"singleInstance"活動僅可以被實例化一次。因為這些活動是一個任務的根,這個限制意味著設備上一個時間只有不多於一個任務的實例。
  • 是否允許實例所在任務有其他活動。"singleInstance"活動所在任務只有它一個活動。如果他啟動別的活動,那些活動將啟動到不同的任務中,無論它的模式如何——就好像Intent對象包含FLAG_ACTIVITY_NEW_TASK標志。在所有其他方面,"singleInstance"模式等同於"singleTask"模式。
    其它三種模式允許多個活動屬於一個任務。"singleTask"活動總是任務的根活動,但是它能啟動其他活動到它的任務。"standard"或"singleTop "活動的實例可以出現的棧中的任何位置。
  • 響應一個意圖時是否需要生成類的新實例。對於默認的"standard"模式,創建新的實例去響應每一個新的意圖。每個實例僅處理一個意圖。對於"singleTop "模式,一個類已存在的實例可以重新用了處理新的意圖,如果它位於目標任務的活動棧的棧頂。如果不是在棧頂,就不可以重用。相反,將創建一個新的實例並壓入棧頂。
    例如,一個任務的活動棧由根活動A、B、C和D組成,順序為A-B-C-D。當一個意圖到達請求類型D時,如果D是默認的"standard"模式,將產生D類的新實例且棧變為A-B-C-D-D。然而,如果D的啟動模式是"singleTop ",已存在的D實例將去處理新的意圖(因為它在棧頂)且棧仍然是A-B-C-D。
    如果,另一方面,到達的意圖是請求類型B時,一個B的新實例將啟動而不管B的模式是"standard"還是"singleTop "(因為B不是在棧頂),因此棧的結構為A-B-C-D-B。
    如前所述,"singleTask"和"singleInstance"活動僅可以被實例化一次,因此他們的實例將處理所有的新意圖。一個"singleInstance"活動總是在棧頂(因為僅有一個活動在任務中),因此它總是在可以處理意圖的位置。然而,一個"singleTask"活動在棧中可能有或可能沒有其他活動在它上面。如果有,即它不在處理意圖的位置,意圖會被丟棄(即使意圖被丟棄了,它的到來使任務轉到並保持在前台運行)

當一個已存在的活動被請求處理一個新的意圖,Intent對象將通過onNewIntent()調用傳到活動。(產生啟動活動的意圖對象可以由getIntent()獲取。)

注意到當一個活動的新實例被創建去處理新意圖時,用戶總是可以按返回鍵返回到之前的狀態(之前的活動)。但是當一個已存在的活動實例去處理新意圖是,用戶不可以按返回鍵返回到意圖到達之前的狀態。

4、清除棧(Clearing the stack)

如果用戶離開一個任務很長時間,系統將會清除根活動之外的活動。當用戶再次返回到這個任務時,像用戶離開時一樣,僅顯示初始的活動。這個想法是,一段時間後,用戶可能已經放棄之前做的東西,及返回任務做新的事情。這是默認情況,有些活動屬性可以用來控制和改變這個行為。

  • alwaysRetainTaskState屬性
    如果在任務的根活動中這個屬性被設置為"true",剛才描述的默認行為將不會發生。任務將保留所有的活動在它的棧中,甚至是離開很長一段時間。
  • clearTaskOnLaunch屬性
    如果在任務的根活動中這個屬性被設置為"true",只有用戶離開就清除根活動之外的活動。換句話說,它與alwaysRetainTaskState截然相反。用戶總是返回到任務的初始狀態,甚至是只離開一會。
  • finishOnTaskLaunch屬性
    這個屬性類似於clearTaskOnLaunch,但是它作用於單個活動,而不是整個任務。而且它能移除任何活動,包括根活動。當它被設置為"true",任務本次會話的活動的部分還存在,如果用戶離開並返回到任務時,它將不再存在。

有其他的方法強制從棧中移除活動。如果Intent對象包含FLAG_ACTIVITY_CLEAR_TOP標志,目標任務已經有一個指定類型的活動實例,棧中該實例上面的其它活動將被移除而使它置於棧頂響應意圖。如果指定的活動的啟動類型是"standard",它自己也將被移除出棧,且一個新的實例將被啟動去處理到來的意圖。這是因為當模式是"standard"時,總是創建一個新的實例去處理新的意圖。

FLAG_ACTIVITY_CLEAR_TOP標志經常與FLAG_ACTIVITY_NEW_TASK一起使用。當一起使用時,這些標志的方式是定位到另一個任務中的已存在的活動並把它放到可以處理意圖的位置。

5、啟動任務(Starting tasks)

通過給定活動一個意圖過濾器"android.intent.action.MAIN"作為指定行為(action)和"android.intent.category.LAUNCHER"指定種類(category),活動就被設置為任務的入口點了。上篇Android開發之旅:應用程序基礎及組件(續)第四節Intent過濾器中我們舉了這樣一個例子,它將導致該活動的圖標(icon)和標簽(label)顯示在應用程序啟動器,給用戶啟動它或啟動之後任意時候返回到它。

它的第二個功能非常重要:用戶可以離開任務且之後可以返回到它。基於這個原因,兩個啟動模式"singleTask"和"singleInstance"標記活動總是初始化一個任務來響應意圖,僅可以使用在有MAINLAUNCHER過濾器的活動中。想象一下,如果沒有這個過濾器將會發生什麼:一個意圖啟動一個"singleTask"活動,開始一個新任務,用戶在任務中做一些操作。然後用戶按下HOME鍵,任務現在退到後台運行且被主屏幕遮蔽住。而且,由於活動不在應用程序啟動器中顯示,用戶無法再返回。

類似的困難也出現在FLAG_ACTIVITY_NEW_TASK標志。如果這個標志導致一個活動開始一個新的任務且用戶按HOME鍵離開它,就必須要有某種方法是用戶能夠導航回來。一些實體(如通知管理器)總是在外部任務啟動活動,從不作為他們自己的一部分,因此他們總是將帶FLAG_ACTIVITY_NEW_TASK標志的意圖傳到startActivity()方法啟動活動。如果你有活動能調用外部實體,可以使用此標志,注意用戶有一個獨立的方式返回到開始的任務。

如果您希望用戶離開活動後就不能再回到這個活動,可以將<activity>元素的finishOnTaskLaunch屬性設置為"true"。可以參見清除棧那節。

轉自:http://www.cnblogs.com/skynet/archive/2010/04/19/1715320.html

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved