2021-11-04Android的四種啟動模式(LaunchMode)

1.為什么要使用啟動模式崇裁?

在我們的Android開發(fā)之中奔缠,當(dāng)我們多次啟動同一個Activity的時候,系統(tǒng)匯創(chuàng)將多個重復(fù)的實(shí)例氮块,將他們放到任務(wù)棧之中绍载。當(dāng)我們點(diǎn)擊返回鍵的時候,這些Activity實(shí)例又將從任務(wù)棧中一一移除滔蝉,遵循椈骼埽“后進(jìn)先出”的原則。

2.啟動模式的分類

1.默認(rèn)模式 Standard

說明: Android創(chuàng)建Activity時的默認(rèn)模式蝠引,假設(shè)沒有為Activity設(shè)置啟動模式的話阳谍,默覺得標(biāo)準(zhǔn)模式。每次啟動一個Activity都會又一次創(chuàng)建一個新的實(shí)例入棧螃概,無論這個實(shí)例是否存在矫夯。

生命周期:如上所看到的,每次被創(chuàng)建的實(shí)例Activity 的生命周期符合典型情況吊洼,它的onCreate训貌、onStart、onResume都會被調(diào)用。

  • 在Manifest中配置:對于標(biāo)準(zhǔn)模式,android:launchMode=”standard”可以不寫递沪,因?yàn)槟J(rèn)就是standard模式豺鼻。
<activity
    android:name=".StandardActivity"
    android:launchMode="standard" >
</activity>
  • 啟動Activity的時候。在Intent中指定啟動模式去創(chuàng)建Activity

通過Intent的addFlags方法去動態(tài)的指定一個啟動模式款慨。

        Intent intent = new Intent();
        intent.setClass(context, MainActivity.class);
        context.startActivity(intent);

這時我們不需要去設(shè)置啟動Flags拘领,默認(rèn)就是standard啟動

2.SingleTop 棧頂復(fù)用模式

說明:分兩種處理情況:須要創(chuàng)建的Activity已經(jīng)處于棧頂時,此時會直接復(fù)用棧頂?shù)腁ctivity樱调。不會再創(chuàng)建新的Activity约素;若須要創(chuàng)建的Activity不處于棧頂,此時會又一次創(chuàng)建一個新的Activity入棧笆凌,同Standard模式一樣圣猎。

生命周期:若情況一中棧頂?shù)腁ctivity被直接復(fù)用時,它的onCreate乞而、onStart不會被系統(tǒng)調(diào)用送悔,由于它并沒有發(fā)生改變∽δ#可是一個新的方法 onNewIntent會被回調(diào)(Activity被正常創(chuàng)建時不會回調(diào)此方法)欠啤。

  • 在 Manifest.xml中指定Activity啟動模式
        <activity android:name="..activity.MultiportActivity" android:launchMode="singleTop"/>
  • 啟動Activity時。在Intent中指定啟動模式去創(chuàng)建Activity
        Intent intent = new Intent();
        intent.setClass(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        context.startActivity(intent);

這里的FLAG_ACTIVITY_SINGLE_TOP就是我們設(shè)置的標(biāo)記位屋灌,作用就是為Activity指定“singleTop”啟動模式

3.棧內(nèi)復(fù)用模式

說明:若須要創(chuàng)建的Activity已經(jīng)處于棧中時洁段,此時不會創(chuàng)建新的Activity,而是將存在棧中的Activity上面的其他Activity所有銷毀共郭,使它成為棧頂祠丝。

生命周期:同SingleTop 模式中的情況一同樣。僅僅會又一次回調(diào)Activity中的 onNewIntent方法

  • 在Manifest中配置:
        <activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/>
  • 啟動Activity時除嘹。在Intent中指定啟動模式去創(chuàng)建Activity
        Intent intent = new Intent();
        intent.setClass(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);

這里的FLAG_ACTIVITY_NEW_TASK就是我們設(shè)置的標(biāo)記位写半,作用就是將Activity的啟動模式設(shè)置為singleTask

4.SingleInstance:單例模式的實(shí)現(xiàn)

  • 在Manifest中配置:
        <activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/>

這里的SingleInstance才是四種啟動模式中的重點(diǎn),它具備所有的SingleTask的特點(diǎn)尉咕,就是一種加強(qiáng)的singleTask叠蝇。但是和別的四種啟動模式不同的是:這種啟動模式會單獨(dú)的創(chuàng)建一個任務(wù)棧,上面的三種啟動模式都是存在于同一個任務(wù)棧之中年缎,而這種的模式存在于另一個任務(wù)棧之中悔捶。這樣的存在模式使用的時候可能存在這一些問題,下面我們在進(jìn)行分析晦款。
我們定義了ActivityA和ActivitySecond兩個界面
當(dāng)我們啟動ActivityA后:

image.png

點(diǎn)擊按鈕進(jìn)入ActivitySecond
image.png


當(dāng)我們退出去之后暫時退出去后炎功,重新進(jìn)入后返回的結(jié)果:
image.png

這里的原因是:當(dāng)我們重新進(jìn)入的時候,我們會重新的在主任務(wù)棧進(jìn)行查找缓溅,若沒有就會進(jìn)行創(chuàng)建蛇损,但是我們的SecondActivity在另外的一個任務(wù)棧之中,這樣當(dāng)我們使用了home鍵暫時的退出程序后再進(jìn)入,此時會調(diào)用主任務(wù)棧中棧頂Activity的onRestart淤齐,不會調(diào)
用SecondActivity的onRestart股囊。

想著查詢一些資料找到解決的辦法,但是后來發(fā)現(xiàn)其實(shí)這個問題根本不需要解決更啄。

因?yàn)槲覀兇藭r根本不需要將我們的launchMode設(shè)置為singleInstance稚疹,這樣的啟動模式只會運(yùn)用在一些特定的需要獨(dú)立棧操作的應(yīng)用上面。比如說:呼叫來電界面祭务。當(dāng)我們正在A應(yīng)用中看視頻的時候内狗,接收到來電,點(diǎn)擊進(jìn)入到來電詳情界面义锥,當(dāng)我們點(diǎn)擊返回之后就回到A視頻的界面柳沙,這樣就不會干擾到用戶之前的操作。
這個時候我們只會產(chǎn)生一個單獨(dú)運(yùn)行的Activity的界面拌倍,這個Activiyt會具有全局唯一性赂鲤,整個系統(tǒng)之中只會存在一個這樣的實(shí)例;

其實(shí)上面的呼叫來電的界面和我們的ActivitySecond界面大同小異柱恤,我們的ActivityA就相當(dāng)于上面的應(yīng)用A数初,只不過,當(dāng)我們退出通話界面的時候梗顺,系統(tǒng)會掛起通話界面也就是實(shí)現(xiàn)onPause泡孩,但是此時通話任務(wù)任然的進(jìn)行,通話界面之中雖然可以可以控制通話的結(jié)束荚守,但是兩者的生命周期卻是沒有進(jìn)行綁定珍德。當(dāng)我們的通話任務(wù)結(jié)束的時候才能夠?qū)νㄔ捊缑孢M(jìn)行銷毀。
這樣的功能都是可以在我們的ActivitySecond界面的基礎(chǔ)之上進(jìn)行實(shí)現(xiàn)矗漾。

3.復(fù)用Activity時的生命周期回調(diào)

由于當(dāng)一個Activity設(shè)置了SingleTop或者SingleTask模式后,跳轉(zhuǎn)此Activity出現(xiàn)復(fù)用原有Activity的情況時薄料,此Activity的onCreate方法將不會再次運(yùn)行敞贡。onCreate方法僅僅會在第一次創(chuàng)建Activity時被運(yùn)行。

而一般onCreate方法中會進(jìn)行該頁面的數(shù)據(jù)初始化摄职、UI初始化誊役,假設(shè)頁面的展示數(shù)據(jù)無關(guān)頁面跳轉(zhuǎn)傳遞的參數(shù),則不必操心此問題谷市,若頁面展示的數(shù)據(jù)就是通過getInten() 方法來獲取蛔垢,那么問題就會出現(xiàn):getInten()獲取的一直都是老數(shù)據(jù),根本無法接收跳轉(zhuǎn)時傳送的新數(shù)據(jù)迫悠!

public class CourseDetailActivity extends BaseActivity{
  ......
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_course_detail_layout);
        initData();
        initView();
    }
 
   //初始化數(shù)據(jù)
    private void initData() {
        Intent intent = getIntent();
        mCourseID = intent.getStringExtra(COURSE_ID);
    }
 
    //初始化UI
    private void initView() {
    ......
    }
    ......
}

以上代碼中的CourseDetailActivity在配置文件里設(shè)置了啟動模式是SingleTop模式鹏漆,依據(jù)上面啟動模式的介紹可得知,當(dāng)CourseDetailActivity處于棧頂時。再次跳轉(zhuǎn)頁面到CourseDetailActivity時會直接復(fù)用原有的Activity艺玲,并且此頁面須要展示的數(shù)據(jù)是從getIntent()方法得來括蝠,可是initData()方法不會再次被調(diào)用,此時頁面就無法顯示新的數(shù)據(jù)饭聚。

當(dāng)然這樣的情況系統(tǒng)早就為我們想過了忌警,這時我們須要另外一個回調(diào) onNewIntent(Intent intent)方法。當(dāng)我們復(fù)用Activity的時候就會調(diào)用此方法秒梳,不復(fù)用就不會調(diào)用法绵。此方法會傳入最新的intent,這樣我們就能夠解決上述問題酪碘。這里建議的方法是又一次去setIntent礼烈。然后又一次去初始化數(shù)據(jù)和UI。代碼例如以下所看到的:

/*
* 復(fù)用Activity時的生命周期回調(diào)
*/
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        initData();
        initView();
    }
那么onNewIntent都會在什么情況下調(diào)用呢婆跑?

前提:ActivityA已經(jīng)啟動過,處于當(dāng)前應(yīng)用的Activity堆棧中;

當(dāng)ActivityA的LaunchMode為SingleTop時此熬,如果ActivityA在棧頂,且現(xiàn)在要再啟動ActivityA,這時會調(diào)用onNewIntent()方法

當(dāng)ActivityA的LaunchMode為SingleInstance,SingleTask時,如果已經(jīng)ActivityA已經(jīng)在堆棧中滑进,那么此時會調(diào)用onNewIntent()方法

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末犀忱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扶关,更是在濱河造成了極大的恐慌阴汇,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件节槐,死亡現(xiàn)場離奇詭異搀庶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)铜异,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門哥倔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人揍庄,你說我怎么就攤上這事咆蒿。” “怎么了蚂子?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵沃测,是天一觀的道長。 經(jīng)常有香客問我食茎,道長蒂破,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任别渔,我火速辦了婚禮附迷,結(jié)果婚禮上惧互,老公的妹妹穿的比我還像新娘。我一直安慰自己挟秤,他們只是感情好壹哺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艘刚,像睡著了一般管宵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上攀甚,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天箩朴,我揣著相機(jī)與錄音,去河邊找鬼秋度。 笑死炸庞,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的荚斯。 我是一名探鬼主播埠居,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼事期!你這毒婦竟也來了滥壕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兽泣,失蹤者是張志新(化名)和其女友劉穎绎橘,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唠倦,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡称鳞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了稠鼻。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冈止。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖枷餐,靈堂內(nèi)的尸體忽然破棺而出靶瘸,到底是詐尸還是另有隱情,我是刑警寧澤毛肋,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站屋剑,受9級特大地震影響润匙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜唉匾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一孕讳、第九天 我趴在偏房一處隱蔽的房頂上張望匠楚。 院中可真熱鬧,春花似錦厂财、人聲如沸芋簿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽与斤。三九已至,卻和暖如春荚恶,著一層夾襖步出監(jiān)牢的瞬間撩穿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工谒撼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留食寡,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓廓潜,卻偏偏與公主長得像抵皱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辩蛋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容