大家看這個帖子之前先了解一下task,taskAffinity屬性。
在開發一個項目時,會遇到多個頁面跳轉的問題,在Android中通常會使用啓動模式來處理頁面跳轉。Activity的啓動模式有四種:
standard
singleTop
singleTask
singleInstance
接下來將詳細介紹這四種模式
standard模式
standard模式是最基本的模式,也是默認的模式,它不需要在AndroidManifest文件設置。其主要的特點是每次通過Intent打開Activity,都會新建一個該Activity實例放入發出該intent的task的頂部。我們可以通過一個實例來驗證:
public class FirstActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
TextView tv_task= (TextView) findViewById(R.id.tv_task);
tv_task.setText(this.toString());
Button btn_first= (Button) findViewById(R.id.btn_first);
btn_first.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivity(new Intent(FirstActivity.this,FirstActivity.class));
}
});
}
}
點擊button將打開一個FristActivity實例,TextView顯示該實例的信息。
從顯示的信息可以看出創建出了三個不同的FirstActivity實例。當我們按返回鍵時會從當前實例返回到上一個實例。
這是standard模式的工作方式,不管有沒有已存在的實例,都會重新創建一個新的實例放在相應task的棧頂。
上邊是在同一個應用中打開,那麼我們現在再來看看跨應用的情況:
Android5.0之前和之後(包括Android5.0)處理方式是不一樣的,在Android5.0之前跨應用和在同一個應用處理方式是一樣的。但是在Android5.0之後跨應用之間啓動Activity,會創建一個新的Task,新生成的Activity就會放入剛創建的Task中。如圖:
此時我們打開Android任務管理器,可以看到兩個獨立的任務:
singleTop
我們還是先看看上邊的實例,我們在AndroidManifest文件中給FirstActivity設置lunchMode
<activity android:name=".ui.FirstActivity"
android:label="FirstActivity"
android:launchMode="singleTop"/>
運行程序會得到以下結果:
沒錯這次三個的編號是一樣的,也就是說這是一個實例。當按back鍵時直接退出應用程序。
這是因爲當我們把FirstActivity的lunchMode設置成singleTop之後,在每一次啓動FirstActivity時,系統判斷相應的task的棧頂是不是FirstActivity實例,如果是就不在創建新的實例並調用其OnNewIntent方法,如果不是則新建實例並且放在task棧頂!
其實可以看出:standard和singleTop基本上是一樣的(包括跨應用),使用singleTop的Activity也可以創建很多個實例。唯一不同的是,如果調用的目標Activity已經位於調用者的Task的棧頂,則不創建新實例,而是使用當前的這個Activity實例,並調用這個實例的onNewIntent方法
singleTask
singleTask和之前的standard、singleTop有很大的不同。使用singleTask的Activity在系統中只會存在一個實例。
在同一個應用中如果系統中不存在singleTask Activity的實例,那麼就需要創建這個Activity的實例,並且將這個實例放入和調用者相同的Task中並位於棧頂。
如果singleTask Activity實例已然存在,那麼在Activity回退棧中,所有位於該Activity上面的Activity實例都將被銷燬掉(銷燬過程會調用Activity生命週期回調),這樣使得singleTask Activity實例位於棧頂。與此同時,Intent會通過onNewIntent傳遞到這個SingleTask Activity實例。
跨應用啓動Activity時,如果系統中不存在singleTask Activity的實例,那麼講創建一個新的Task,然後創建SingleTask Activity的實例,將其放入新的Task中。如果singleTask Activity所在的應用進程存在,但是singleTask Activity實例不存在,那麼從別的應用啓動這個Activity,新的Activity實例會被創建,並放入到所屬進程所在的Task中,並位於棧頂位置。更復雜的一種情況,如果singleTask Activity實例存在,從其他程序被啓動,那麼這個Activity所在的Task會被移到頂部,並且在這個Task中,位於singleTask Activity實例之上的所有Activity將會被正常銷燬掉。如果我們按返回鍵,那麼我們首先會回退到這個Task中的其他Activity,直到當前Task的Activity回退棧爲空時,纔會返回到調用者的Task。
singleInstance
這個模式和singleTask差不多,因爲他們在系統中都只有一份實例。唯一不同的就是存放singleInstance Activity實例的Task只能存放一個該模式的Activity實例。如果從singleInstance Activity實例啓動另一個Activity,那麼這個Activity實例會放入其他的Task中。同理,如果singleInstance Activity被別的Activity啓動,它也會放入不同於調用者的Task中。
這種模式的使用情況比較罕見,在Launcher中可能使用。或者你確定你需要使Activity只有一個實例。建議謹慎使用。
簡單的介紹了一下四種啓動模式,之後會介紹Intent Flags與啓動模式結合使用的情況。
參考鏈接:Understand Android Activity’s launchMode: standard, singleTop, singleTask and singleInstance
http://droidyue.com/blog/2015/08/16/dive-into-android-activity-launchmode/