一、 Activity的四種加載模式
Activity之間的跳轉,或者說加載一個新的Activity,一般對於開發者來說,都不是一個太難的問題。直到后來隨着不斷的深入,才發現原來Activity的加載還分為四種不同加載模式。靈活的使用合適的加載模式,可以避免產生大量的重復的Activity,從而優化性能,減少系統資源消耗。
四種加載模式具體為:
- standard: 標准模式,一調用startActivity()方法就會產生一個新的實例。
- singleTop: 檢查是否已經存在了一個實例位於Activity Stack的頂部,如果存在就不產生新的實例,反之則調用Activity的newInstance()方法產生一個新實例。
- singleTask: 在一個新的Task中產生這個實例,以后每次調用都會使用此實例,而避免產生新的實例。
- singleInstance: 這個基本上跟singleTask一樣,只是有一點不同,那就是在這個模式下的Activity實例所處的Task中,只能有這一個Activity實例,而不能有其他的實例。
1. 這些啟動模式可以Android清單文件AndroidManifest.xml中,通過<activity>中的launchMode屬性進行設置,如:
<activity android:name="MainActivity" android:launchMode="singleTop"> <intent-filter> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
2. 另外也可以在代碼中通過一些標志進行設置。如:
Intent intent = new Intent(SrcActivity.this, TargetActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent);
四種加載模式的區別如下:
1. 所屬Task的區別:
一般情況下,,“standard”和”singleTop”兩種加載模式 源Activity(即new Intent(arg0,arg1)中的第一個參數)和目標Activity(即new Intent(arg0,arg1)中的第二個參數)在同一個Task內, 除非Intent包括了參數FLAG_ACTIVITY_NEW_TASK,如包含了此參數,目標Activity會起動到新的Task里;
“singleTask”和“singleInstance” 總是把目標Activity作為一個Task的根元素,他們不會被啟動到一個其他Task里。
2. 是否允許多個實例的區別:
二、 跟Task 有關的 Intent對象中內置的Flag
Intent對象在Android開發中起着舉足輕重的作用,其內置了豐富的常量,用於傳遞數據,下面本文將介紹跟Task有關的一些Flag參數
FLAG_ACTIVITY_SINGLE_TOP:
如果Activity位於Activity Stack的頂端,則不再創建一個新的實例。
FLAG_ACTIVITY_NEW_TASK
將使Activity成為一個新Task的開始。
FLAG_ACTIVITY_BROUGHT_TO_FRONT
這個標志一般不是由程序代碼設置的,如在launchMode中設置singleTask模式時系統幫你設定。
FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
這個標志一般不由應用程序代碼設置,如果這個Activity是從歷史記錄里啟動的(常按HOME鍵),那么,系統會幫你設定。
FLAG_ACTIVITY_MULTIPLE_TASK
不建議使用此標志,除非你自己實現了應用程序啟動器。
FLAG_ACTIVITY_CLEAR_TOP
如果目標Activity已經運行於當前的Task中,則關閉Activity Stack中在此Activity上方的所有Activity,然后將此Intent傳遞到該Activity實例內。例如, 假設一個Task的Activity Stack中包含這些Activity:A,B,C,D。如果D調用了startActivity(),並且Intent指向B,那么,C和D都將結束,然后B接 收到這個Intent,因此,目前stack的狀況是:A,B。
FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
如果設置,這將在Task的Activity Stack中設置一個還原點,當Task恢復時,需要清理Activity。例如下一次Task帶着 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED標記進入前台時,這個Activity和它之上的都將關閉,以至於用戶不能再返回到它們,但是可以回到之前的 Activity。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
如果設置,新的Activity不會在最近啟動的Activity的列表中保存。
FLAG_ACTIVITY_FORWARD_RESULT
如果設置,並且這個Intent用於從一個存在的Activity啟動一個新的Activity,那么,這個作為答復目標的Activity將會傳到這個新的Activity中。這種方式 下,新的Activity可以調用setResult(int),並且這個結果值將發送給那個作為答復目標的Activity。
FLAG_ACTIVITY_NO_ANIMATION
這個標志將阻止系統進入下一個Activity時應用Acitivity遷移動畫。
FLAG_ACTIVITY_NO_HISTORY
新的Activity將不再歷史stack中保留。一旦離開,此Activity就關閉了。
FLAG_ACTIVITY_NO_USER_ACTION
這個標志將在Activity暫停之前阻止從最前方的Activity回調的onUserLeaveHint()。
FLAG_ACTIVITY_PREVIOUS_IS_TOP
If set and this intent is being used to launch a new activity from an existing one, the current activity will not be counted as the top activity for deciding whether the new intent should be delivered to the top instead of starting a new one. The previous activity will be used as the top, with the assumption being that the current activity will finish itself immediately.
FLAG_ACTIVITY_REORDER_TO_FRONT
這個標志將引發已經運行的Activity移動到歷史stack的頂端。
FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
If set, and this activity is either being started in a new task or bringing to the top an existing task, then it will be launched as the front door of the task. This will result in the application of any affinities needed to have that task in the proper state (either moving activities to or from it), or simply resetting that task to its initial state if needed.
上面紛雜的Intent內置參數在簡單的Android應用時,可以啟到比較好的控制作用,但是一旦Android應用過於復雜,那么自定一個Activity List以管理Activity不失於一種更好更高效的管理方法。
三、 Affinity 和 新Task
默認情況下,一個應用程序中的所有Activity都有affinity------也就是說,屬於同一個Task中所有Activity有一個設定。然而,每個Activity都可以在元素的taskAffinity特性上設置單獨的值。定義在不同應用程序中的Activity可以共享同一個affinity,或者定義在同一個應用程序中的Activity設置不同的affinity。Affinity在兩種環境下工作:Intent對象包含FLAG_ACTIVITY_NEW_TASK標志,和Activity的allowTaskReparenting特性設置為“true”。
FLAG_ACTIVITY_NEW_TASK:
之前描述的,一個Activity一般通過調用startActivity()啟動並加入到Task中。它同調用者一樣,進入同一個Task。然而,如果傳遞給startActivity()的Intent對象中包含FLAG_ACTIVITY_NEW_TASK時,系統會搜索一個新的Task來容納新的Activity。通常,如標志的名字所示,是一個新的Task。然而,並不是必須是。如果已經存在一個Task與新Activity的affinity相同,這個Activity就會加入到那個Task中。如果不是,啟動一個新的Task。
allowTaskReparenting
如果一個Activity的allowTaskReparenting特性設置為“true”,它就能從啟動的Task中移到有着相同affinity的Task(這個Task進入到前台的時候)。例如,在一個旅游的程序中定義了一個可以報告選擇城市的天氣情況的Activity。它和同一個應用程序的其它Activity一樣,有着相同的Affinity(默認的Affinity),並且它允許重新宿主。你的Activity中的一個啟動了天氣預報,因此,它初始化到和你Activity相同的Task中。然而,當旅游應用程序下一次進入到前台時,天氣預報那個Activity將會重新編排並在那個Task中顯示。如果從用戶的角度出發,一個.apk文件包含多個“應用”的話,你可能希望為關聯的Activity設置不同的affinity。
參考:
activity的task相關 http://www.360doc.com/content/12/0118/10/8134611_180127417.shtml
- activity 加載模式 http://www.cnblogs.com/wisekingokok/archive/2011/08/21/2147879.html
- intent 對象內置flag http://www.cnblogs.com/wisekingokok/archive/2011/08/21/2147897.html
- task and back statck http://developer.android.com/guide/components/tasks-and-back-stack.html