Activity的啟動與管理之圖記表查
Activity 作為AndroidApp重要的組成之一,它的建立、執行和維護也是我們必須知悉的一部分;Activity的建立是由開發人員決定,它的執行與維護則由系統通過任務棧進行協助管理,我們通過配置指定的啟動模式來實現我們App的良好使用

Activity啟動與管理.jpg
Activity的管理——任務棧
任務棧
Android Task 是用來存放Activity例項的容器,Android系統可以通過Task可以有序的對每個Activity進行管理,決定與使用者互動的Activity(也就是棧頂的Activity)
- Android Task是一個棧結構,只有壓棧、出棧的操作,具有先進後出的特點
- 啟動一個Application的時候,系統會為它預設建立一個對應的Task,用來放置根Activity,這裡需要注意一個App可以不止擁有一個任務棧,一個任務棧可以存放來不同應用的Activity
- 任務棧所有的Activity被移除時才會被銷燬,任務棧也可以移至後臺並保留棧內所有的Activity及狀態資訊
-
前臺棧與後臺棧,正在與使用者互動的Activity存在的任務棧即為前臺棧,其他則為後臺棧,假設每個App只有一個任務棧,當我們切換使用APP時可以看到多個任務棧在後臺,正在使用的APP的棧則是前臺棧,當發生跳轉其他應用時,後臺棧被移動至前臺成為前臺棧,此時的返回操作則由前臺棧接手,注意依然是兩個棧
前臺棧切換.png
Activity的啟動模式
正常情況下,當一個Activity啟動了另一個Activity的時候,新啟動的Activity就會置於任務棧的頂端,並處於活動狀態,啟動它的Activity壓入,處於停止狀態,當用戶按下返回鍵或者呼叫finish()方法時,系統會移除頂部Activity,讓後面的Activity恢復活動狀態,而不正常情況下就是給Activity設定特殊的啟動模式使得我們的Activity跳轉有了自定義的管理
模式 | 說明 | 補充 |
---|---|---|
Standard/標準模式 | 可存在多個例項,跳轉到該Activity時會重新例項化並路由Intent給它 | 預設進入啟動它的任務棧中(在5.0之前新啟動的Activity例項會放入傳送Intent的Task的棧的頂部,5.0之後,上述情景會建立一個新的Task,新啟動的Activity就會放入剛建立的Task中 ) |
SingleTop/棧頂唯一 | 可存在多個,只當跳轉時該Activity存在棧頂時進行復用,其他情況下會進行重新例項化 | 比如在某些情況下跳轉某個Activity的操作發生了多次,使用這中模式就可以避免建立多個該Activity;預設任務棧同standard模式 |
SingleTask/棧內唯一 | 不存在多個,該Activity存在單獨的棧內,且不存在其他Activity,不存在時進行例項化並存放至單獨的棧內 | 例如App的登入介面,在退出到登入介面時,使用該模式可以不用對其他登入後的Activity做出棧操作而是自動清空原來之上的所有Activity |
SingleInstance/棧內唯一 | 不存在多個,該Activity存在單獨的棧內,且不存在其他Activity,不存在時進行例項化並存放至單獨的棧內 | 新建棧來存放,例如撥號介面 |
Activity的配置啟動
Activity的啟動模式可以通過清單檔案和使用Intent設定Activity Flags來配置。
android:launchMode="standard/singleTop/singleTask/singleInstance"
- 寫法
Intent intent = new Intent(SActivity.this, STestActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
- Activity Flags
屬性名 | 說明 | 補充 |
---|---|---|
FLAG_ACTIVITY_NEW_TASK | 使用一個新的Task來啟動一個Activity,但啟動的每個Activity都將在一個新的Task | 該Flag通常使用在從Service中啟動Activity的場景,由於Service中並不存在Activity棧,所以使用該Flag來建立一個新的Activity棧,並建立新的Activity例項 |
FLAG_ACTIVITY_SINGLE_TOP | 使用singletop模式啟動一個Activity |
與指定android:launchMode="singleTop"
效果相同。 |
FLAG_ACTIVITY_CLEAR_TOP | 使用SingleTask模式來啟動一個Activity |
,與指定android:launchMode="singleTask"
效果相同。 |
FLAG_ACTIVITY_NO_HISTORY | Activity使用這種模式啟動Activity,當該Activity啟動其他Activity後,該Activity就消失了,不會保留在Activity棧中。 | |
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | 具有這個標記的Activity將不會出現在歷史Activity列表中 |
帶返回的啟動Activity方法——StartActivityForResult
開發當中Activity與Activity的資料互動是通過Intent來進行,但普通的startActivity是沒辦法拿到將要啟動的頁面的互動後的資料,例如進入拍照頁面後獲取拍到的相片,因此Android這裡設計了StartActivityForResult這一方法滿足這一需求
- 使用介面跳轉
//REQUEST_CODE 為大於0小於65535(0xFFFF)的整數, Intent intent = new Intent(this, XXXActivity.class); startActivityForResult(intent,REQUEST_CODE);
- 使用介面的接收
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //requestCode 用於判斷是否啟動哪個Activity的返回結果 //resultCode與Activity.RESULT_CANCELED、Activity.RESULT_OK判斷是否取成功 //data傳遞資料的載體 }
- 跳轉介面的返回
Intent data = new Intent(); setResult(Activity.RESULT_OK, data); finish();
補充說明
- 開發藝術與探索中提到使用非Activity型別的context(ApplicationContext)啟動標準模式的Activity會報錯,這是因為此時無法確認新建的Activity所存放的棧,可以為此Activity指定FLAG_NEW_ACTIVITY_TASK標記位來避免報錯
- REQUEST_CODE的大小限制是原始碼中校驗規則限制,一旦超出範圍則會丟擲異常
/** * Checks whether the given request code is a valid code by masking it with 0xffff0000. Throws * an {@link IllegalArgumentException} if the code is not valid. */ static void checkForValidRequestCode(int requestCode) { if ((requestCode & 0xffff0000) != 0) { throw new IllegalArgumentException("Can only use lower 16 bits for requestCode"); } }