學習筆記| (二) 元件篇之Activity啟動模式
一.啟動模式:
1.Standard
- 預設是standard模式
- A啟動B,B就會進入A所在的任務棧中
- 不管要啟動的activity在任務棧中是否存在,都會重新建立一個新的例項
- 在Activity A中不斷的啟動自己
android:launchMode="standard"
MainActivity-->com.code.MainActivity@2cdaf713-->棧:885 MainActivity-->com.code.MainActivity@2d2219ca-->棧:885 MainActivity-->com.code.MainActivity@177c5ca6-->棧:885
2.SingleTop
- A啟動B,B就會進入A所在的任務棧中
- 要啟動的Activity如果處於棧頂,不會建立新的例項,而會呼叫onNewIntent()方法;如果不在棧頂,則會建立新的例項;
- B的啟動方式是SingleTop,A中啟動B,在B中再啟動B
android:launchMode="singleTop"
A:MainActivity-->com.code.MainActivity@2cdaf713-->棧:887 B:onCreate-->com.code.BActivity@2d2219ca-->棧:887 B:onNewIntent-->com.code.BActivity@2d2219ca-->棧:887 B:onNewIntent-->com.code.BActivity@2d2219ca-->棧:887
3.SingleTask
- 啟動A,會先看是否存在A想要的任務棧,不存在,建立任務棧,把A放進去;存在,判斷是否存在A的例項,存在,則會呼叫onNewIntent(),預設具有clearTop的效果,會清空它上面的所有activity,讓它們出棧,並將要啟動的activity置於棧頂;否則會建立新的例項;
- B的啟動模式是SingleTask,A啟動B,B啟動C,C中再啟動B
android:launchMode="singleTask"
A:MainActivity-->com.code.MainActivity@2cdaf713-->棧:889 B:onCreate-->com.code.BActivity@2d2219ca-->棧:889 C:onCreate-->com.code.CActivity@1490bfe8-->棧:889 B:onNewIntent-->com.code.BActivity@2d2219ca-->棧:889
4.SingleInstance
- A啟動B,B會進入一個新的任務棧中
- SingleInstance是SingTask的升級版,它具有SingleInstance的所有特性,要啟動的Activity會在一個新的任務棧中建立,如果之後要再啟動這個Activity,先看任務棧中是否存在這個Activity,存在,呼叫onNewIntant(),並將上面的Activity清空;否則建立一個新的例項;
- B的啟動模式是SingleInstance,A啟動B後,B再啟動B
android:launchMode="singleInstance"
A:MainActivity-->com.code.MainActivity@2cdaf713-->棧:892 B:onCreate-->com.code.BActivity@2d2219ca-->棧:893 B:onNewIntent-->com.code.BActivity@2d2219ca-->棧:893
注意
getApplication().startActivity(new Intent(this,BActivity.class));
如果這樣啟動一個Activity,會報錯:
Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activitycontext requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
之前在專案中,來電時會出一個Activity,就報了這個錯,這個錯是什麼原因導致的呢?
因為 getApplication() 是非Activity型別的context,並不存在任務棧一說,所以啟動B的時候,B會新增到 getApplication() 所在的任務棧,這就矛盾了,這時候並不存在任務棧,所以只能將B新增到一個新的任務棧中
任務棧
- 分為前臺任務棧和後臺任務棧
- 在 SingleTask 中多次提到了任務棧,那麼什麼是任務棧呢?
這裡涉及到一個名詞“ TaskAffinity ”,可以叫“任務相關性”,它是任務棧的名字,所有Activity都預設是包名。 - TaskAffinity 只有和"SingleTask"
或者“allowTaskReparenting”一起使用時才起作用,如果 TaskAffinity 指定為當前包名,也是無效的,因為預設就是包名,沒啥用處。 - TaskAffinity 和"SingleTask"一起使用
<activity android:name=".BActivity" android:launchMode="singleTask" android:taskAffinity="com.app.b"/>
也就是所有taskAffinity相同的會在一個任務棧中存在;
-
TaskAffinity和"allowTaskReparenting"一起使用, app A啟動了 app B的 Activity C(allowTaskReparenting為true),這時候啟動app B了,那麼在B上顯示的是哪一個頁面呢?
答案是Activity C。
分析:
A啟動了頁面c,這時候c的 TaskAffinity 和A的 TaskAffinity 肯定不同,但是又沒有c所需要的任務棧存在,所以c只能現在A的任務棧中執行,這時候B打開了,系統發現c所需要的任務棧存在了,就會將c移到B的任務棧中,所以會看到B上顯示的是c頁面。
-
A,B,C三個Activity,B和C的TaskAffinity為com.app.task,啟動模式為SingleTask;A啟動B後,B啟動C,C再啟動A後,A啟動B後,點選back點選顯示誰?
分析:
①定義兩個任務棧S1和S2
②A和B的TaskAffinity不同,A啟動B的時候,不存在名為"com.app.task"的任務棧,所以建立一個新的任務棧S2;
③B啟動C,他們的TaskAffinity相同,任務棧已存在,將C直接入棧,置於B的上面;
④C啟動A,A的啟動模式是standard,會在S2中入棧;
⑤A啟動B,這時候要啟動的B在S2中已經存在了,就將它上面的CA全部出棧,S2中只剩下B;
⑥再點Back鍵,B出棧,直接返回桌面,因為這時候最開始A所在的S1任務棧是後臺棧;這時候後臺任務棧就變成前臺任務棧了,A顯示,再次點選back鍵,返回桌面;
通過Intent標誌位指定啟動模式
-
和manifest中設定有什麼區別?
manifest中無法設定 Intent.FLAG_ACTIVITY_CLEAR_TOP ;
Intent方式無法設定SingleInstance;
-
常用的幾個:
①這個和在xml中的效果是一樣的,singleTop
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
②這個和在xml中的效果是一樣的,singleTask
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
③這個表示將上面的activity都清空出棧,一般和②搭配使用, 如果要啟動的activity存在,則呼叫onNewIntent(),清空它上面的activity;如果要啟動的activity是standard模式,則它會連同它上面的activity一塊清空,然後建立新的例項 ;
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
④這個表示將要啟動的activity不會新增到歷史activity中,和在xml中加入 android:excludeFromRecents="true" 效果一樣
intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Intent-filter匹配規則

intent-filter匹配規則.png