一、生命周期
(1)Activity跳轉(zhuǎn)時抱慌,舊Activity的onPause必須先執(zhí)行完霜威,新Activity的onResume才會執(zhí)行酪刀。所以不能在onPause中做太耗時的操作,否則會影響到新Activity的顯示钮孵。
(2)Activity的onStop方法不回調(diào)的情況:
- 新Activity采用了透明主題
// 在AndroidManifest.xml中注冊時
android:theme="@android:style/Theme.Translucent"
- 新Activity采用了Dialog主題
android:theme="@android:style/Theme.Dialog"
注意:在當(dāng)前Activity創(chuàng)建并彈出一個Dialog并不會回調(diào)onPause和onStop
(3)當(dāng)資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致Activity被殺死并重新創(chuàng)建時骂倘,系統(tǒng)會調(diào)用onSaveInstanceState和onRestoreInstanceState來存儲和恢復(fù)數(shù)據(jù)。當(dāng)然也可以從onCreate的參數(shù)Bundle savedInstanceState去獲取恢復(fù)數(shù)據(jù)巴席,但此時一定要判斷savedInstanceState是否為null稠茂。如果當(dāng)系統(tǒng)配置發(fā)生改變后,不想系統(tǒng)重新創(chuàng)建Activity情妖,可以給Activity指定configChanges屬性睬关,指定的屬性發(fā)生改變時,Activity不會被重新創(chuàng)建毡证,同時系統(tǒng)會調(diào)用Activity的onConfigurationChanged方法电爹。例如:
android:configChanges="orientation|keyboardHidden|screenSize"
- orientation:屏幕方向發(fā)生了改變,這是最常用的料睛,比如旋轉(zhuǎn)了手機(jī)屏幕
- keyboardHidden:鍵盤的可訪問性發(fā)生了改變丐箩,比如用戶調(diào)出了鍵盤
- screenSize:屏幕的尺寸信息發(fā)生了改變,比如旋轉(zhuǎn)了手機(jī)屏幕
二恤煞、Activity四種啟動模式
啟動Activity時屎勘,系統(tǒng)會創(chuàng)建Activity實例并將它放入任務(wù)棧中。任務(wù)棧是一種“先進(jìn)后出”的棧結(jié)構(gòu)居扒,當(dāng)棧中無任何Activity時概漱,系統(tǒng)就會回收這個任務(wù)棧。
(1)standard:系統(tǒng)的默認(rèn)模式喜喂。每次啟動一個Activity都會重新創(chuàng)建一個新的實例瓤摧,不管這個實例是否已經(jīng)存在。當(dāng)我們用ApplicationContext去啟動standard模式的Activity會報錯玉吁,這是由于非Activity類型的Context并沒有所謂的任務(wù)棧照弥。解決這個問題的方法是為待啟動的Activity指定FLAG_ACTIVITY_NEW_TASK標(biāo)記位,這樣啟動時就會為它創(chuàng)建一個新的任務(wù)棧进副,此時待啟動Activity實際上是以singleTask模式啟動的这揣。
(2)singleTop:棧頂復(fù)用模式漫谷。在這種模式下徽级,如果新Activity已經(jīng)位于任務(wù)棧的棧頂忌傻,那么此Activity不會被重新創(chuàng)建赏寇,同時它的onNewIntent方法會被回調(diào)鳖孤,onCreate轻抱、onStart不會被調(diào)用奕剃。如果新Activity的實例已存在但不是位于棧頂渣窜,那么它仍然會被重新創(chuàng)建吏垮。
/**
* @param intent
* 通過intent可以取出當(dāng)前請求的信息
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
(3)singleTask:棧內(nèi)復(fù)用模式障涯。這是一種單實例模式罐旗,在這種模式下,只要Activity在一個棧中存在唯蝶,那么多次啟動此Activity都不會重新創(chuàng)建實例九秀,和singleTop一樣,系統(tǒng)也會回調(diào)其onNewIntent方法粘我。具體一點鼓蜒,當(dāng)一個具有singleTask模式的Activity請求啟動后,比如Activity A征字,系統(tǒng)首先會尋找是否存在A想要的任務(wù)棧都弹,如果不存在,就重新創(chuàng)建一個任務(wù)棧匙姜,然后創(chuàng)建A的實例后把A放入棧中畅厢。如果存在A所需要的任務(wù)棧,這時要看A是否在棧中有實例存在氮昧,如果實例不存在框杜,就創(chuàng)建A的實例并把A壓入棧中;如果有實例存在袖肥,那么系統(tǒng)就會把A調(diào)到棧頂并調(diào)用它的onNewIntent方法咪辱,同時由于singleTask默認(rèn)具有clearTop的效果,會導(dǎo)致棧內(nèi)所有在A上面的Activity全部出棧椎组。
(4)singleInstance:單實例模式油狂。這是一種加強(qiáng)的singleTask模式,它除了具有singleTask模式的所有特性外庐杨,還加強(qiáng)了一點选调,那就是具有此種模式的Activity只能單獨地位于一個任務(wù)棧中夹供。
總結(jié)
在沒有設(shè)置taskAffinity的前提下灵份,除了singleInstance模式外,誰啟動了這個Activity哮洽,那么這個Activity就運行在啟動它的那個Activity所在的棧中填渠。
三、指定啟動模式
(1)通過AndroidMenifest為Activity指定啟動模式
<activity
android:name=".SecondActivity"
android:configChanges="orientation"
android:launchMode="singleTop" />
(2)通過在Intent中設(shè)置標(biāo)志位來為Activity指定啟動模式
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
優(yōu)先級上鸟辅,第二種方式的優(yōu)先級要高于第一種氛什,當(dāng)兩種同時存在時,以第二種方式為準(zhǔn)匪凉;第一種方式無法直接為Activity設(shè)定FLAG_ACTIVITY_CLEAR_TOP標(biāo)識枪眉,而第二種方式無法為Activity指定singleInstance模式。
四再层、Activity的Flags
Activity的標(biāo)志位有很多贸铜,有的標(biāo)志位可以設(shè)定Activity的啟動模式堡纬,有的標(biāo)志位可以影響Activity的運行狀態(tài),下面主要介紹幾種比較常用的標(biāo)志位:
(1)FLAG_ACTIVITY_NEW_TASK
這個標(biāo)志位的作用是為Activity指定“singleTask”啟動模式蒿秦,其效果和在XML中指定該啟動模式相同烤镐。
(2)FLAG_ACTIVITY_SINGLE_TOP
這個標(biāo)志位的作用是為Activity指定“singleTop”啟動模式,其效果和在XML中指定該啟動模式相同棍鳖。
(3)FLAG_ACTIVITY_CLEAR_TOP
具有此標(biāo)志位的Activity炮叶,當(dāng)它啟動時,在同一個任務(wù)棧中所有位于它上面的Activity都要出棧渡处。這個標(biāo)志位一般會和singleTask啟動模式一起出現(xiàn)镜悉,在這種情況下,被啟動Activity的實例如果已經(jīng)存在医瘫,那么系統(tǒng)就會調(diào)用它的onNewIntent积瞒。如果被啟動的Activity采用standard模式啟動,那么它連同它之上的Activity都要出棧登下,系統(tǒng)會創(chuàng)建新的Activity實例并放入棧頂茫孔。singleTask啟動模式默認(rèn)就具有此標(biāo)志位的效果。
(4)FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有這個標(biāo)志位的Activity不會出現(xiàn)在歷史Activity的列表中被芳,當(dāng)某些情況下我們不希望用戶通過歷史列表回到我們的Activity的時候這個標(biāo)志位比較有用缰贝。它等同于在XML中指定Activity的屬性android:excludeFromRecents="true"。
五畔濒、任務(wù)棧
任務(wù)棧分為前臺任務(wù)棧和后臺任務(wù)棧剩晴。當(dāng)用戶開啟了一個新的任務(wù)棧,或者點擊Home鍵回到主屏幕的時候侵状,之前任務(wù)就會被轉(zhuǎn)移到后臺赞弥。當(dāng)任務(wù)處于后臺狀態(tài)的時候,任務(wù)棧中所有的Activity都會進(jìn)入暫停狀態(tài)趣兄,但這些Activity在棧中的順序都會原封不動地保留著绽左。默認(rèn)情況下,所有Activity啟動后艇潭,所在的任務(wù)棧的名字都為應(yīng)用的包名拼窥,但是如果在AndroidMenifest中為Activity指定了taskAffinity屬性,此時Activity啟動后所在的任務(wù)棧名字就是指定的taskAffinity屬性的值蹋凝。
taskAffinity屬性主要和singleTask啟動模式或者allowTaskReparenting屬性配對使用鲁纠,在其他情況下沒有意義。當(dāng)taskAffinity和singleTask啟動模式配對使用的時候鳍寂,它是具有該模式的Activity的目前任務(wù)棧的名字改含,待啟動的Activity會運行在名字和taskAffinity相同的任務(wù)棧中。