在Android設計中遇到這樣一個問題:
Activity A,在中設置它的一個爲
AndroidManifest.xml代碼
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
A的launchMode爲“singleTask”。
Activity B,設置launchMode爲“standard”。
這樣,A作爲啓動應用的入口Activity;在A中進行某個操作可以跳轉到B。
如果此時,點擊‘Home’鍵返回到Home Screen後,再次點擊應用圖標進入應用,出現的界面爲A,而非B。通過一些測試,發現,在重新進入應用時,在Back stack中,位於A之上的其他Activity均被銷燬了。
開發的時候,由於用到了singleTask用法不當,造成了一些不必要的麻煩,現總結如下:
現有Activity:A,B,C,D;啓動順序是A->B->C->D,其中,B是singleTask的。
A到B後,A finish掉;B到C後,B不 finish; C到D後,C不 finish;在D啓動B,就可以一下子將C、D kill掉,只保留B。但是,
這個時候你從B退出(整個程序退出了),長按Home鍵啓動,進來的第一個是B,而不是A,這就已經不對了; 而且, 剛纔就算你不退出,從B再進到C,按Home,再長按Home進入,回來的是B而不是C。
解決方案如下:
將singleTask改成singleTop。
這樣以來,剛纔從D啓動B的時候,就要用intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
也就是說,singleTask會自動執行clear top, 而singleTop需要手動;而從Home鍵啓動,如果是singleTask的話就自動clear top了,所以到不了想要到的Activity。
這樣就解決了問題,但是上面的說法是個人的理解。
Activity有四種加載模式:
standard
標準啓動模式,也是activity的默認啓動模式。在這種模式下啓動的activity可以被多次實例化,即在同一個任務中可以存在多個activity的實例,每個實例都會處理一個Intent對象。如果Activity A的啓動模式爲standard,並且A已經啓動,在A中再次啓動Activity A,即調用startActivity(new Intent(this,A.class)),會在A的上面再次啓動一個A的實例,即當前的桟中的狀態爲A-->A。
singleTop
接下來就是singleTop模式。它的表現幾乎和standard模式一模一樣,一個singleTop Activity 的實例可以無限多,唯一的區別是如果在棧頂已經有一個相同類型的Activity實例,Intent不會再創建一個Activity,而是通過onNewIntent()被髮送到現有的Activity。
singleTask
這種模式和standard以及singleTop有很大不同。singleTask模式的Activity只允許在系統中有一個實例。如果系統中已經有了一個實例,持有這個實例的任務將移動到頂部,同時intent將被通過onNewIntent()發送。如果沒有,則會創建一個新的Activity並置放在合適的任務中。
singleInstance
這個模式非常接近於singleTask,系統中只允許一個Activity的實例存在。區別在於持有這個Activity的任務中只能有一個Activity:即這個單例本身。
設置的位置在AndroidManifest.xml文件中activity元素的Android:launchMode屬性:
<activity android:name="ActB" android:launchMode ="singleTask"></activity>
Intent Flags
除了在AndroidManifest.xml中直接設置launch mode,我們還可以通過叫做 Intent Flags的東西設置更多的行爲,比如:
Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
Task
Task是Android Framework中的一個概念,Task是由一系列相關的Activity組成的,是一組相關Activity的集合。Task是以棧的形式來管理的。
我們在操作軟件的過程中,一定會涉及界面的跳轉。其實在對界面進行跳轉時,Android Framework既能在同一個任務中對Activity進行調度,也能以Task爲單位進行整體調度。在啓動模式爲standard或singleTop時,一般是在同一個任務中對Activity進行調度,而在啓動模式爲singleTask或singleInstance是,一般會對Task進行整體調度。
對Task進行整體調度包括以下操作:
- 按Home鍵,將之前的任務切換到後臺
- 長按Home鍵,會顯示出最近執行過的任務列表
- 在Launcher或HomeScreen點擊app圖標,開啓一個新任務,或者是將已有的任務調度到前臺
- 啓動singleTask模式的Activity時,會在系統中搜尋是否已經存在一個合適的任務,若存在,則會將這個任務調度到前臺以重用這個任務。如果這個任務中已經存在一個要啓動的Activity的實例,則清除這個實例之上的所有Activity,將這個實例顯示給用戶。如果這個已存在的任務中不存在一個要啓動的Activity的實例,則在這個任務的頂端啓動一個實例。若這個任務不存在,則會啓動一個新的任務,在這個新的任務中啓動這個singleTask模式的Activity的一個實例
- 啓動singleInstance的Activity時,會在系統中搜尋是否已經存在一個這個Activity的實例,如果存在,會將這個實例所在的任務調度到前臺,重用這個Activity的實例(該任務中只有這一個Activity),如果不存在,會開啓一個新任務,並在這個新任務中啓動這個singleInstance模式的Activity的一個實例。
參考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0520/2897.html
http://blog.csdn.net/zhangjg_blog/article/details/10923643