Activity啟動模式

一、啟動模式簡介

啟動模式相當于Activity的一個屬性攒砖,不同的啟動模式Activity會有不同的行為表現(xiàn)践宴,這里的行為主要體現(xiàn)在Activity的生命周期陨囊,特別是系統(tǒng)在啟動多個Activity實例的時候,具體差異我們將用實例來說明剧辐。

二寒亥、任務(wù)棧簡介

要了解Activity的啟動模式,就不可避免地涉及到Activity所需的任務(wù)棧荧关。什么是任務(wù)棧呢护盈?android系統(tǒng)每啟動一個新的Activity,都要將該Activity實例放入特定的任務(wù)棧羞酗,而這個任務(wù)棧和一個參數(shù)TaskAffinity有關(guān),這個產(chǎn)生標識了Activity所需的任務(wù)棧的名字腐宋,默認的值為應(yīng)用的包名。值得注意的是檀轨,TaskAffinity屬性主要和singleTask啟動模式(下面將要介紹)或allowTaskReparenting屬性配合使用胸竞,在其他情況下沒有意義。
??既然叫“棽翁眩”卫枝,那么就符合“后進先出”的特點,我們每按一下back鍵讹挎,就有一個Activity實例出棧校赤。

三吆玖、Activity啟動模式

1、standard

標準模式马篮,這是系統(tǒng)的默認模式沾乘。每次啟動一個Activity都會重新創(chuàng)建一個Activity實例,不管這個Activity的實例是否存在浑测。

2翅阵、singleTop

棧頂復用模式。在這種模式下迁央,如果有Activity實例位于任務(wù)棧頂掷匠,那么就不會重新創(chuàng)建Activity實例,同時岖圈,Activity的onNewIntent方法會被回調(diào)讹语。

3、singleTask

棧內(nèi)復用模式蜂科。類似于單例模式募强,只要任務(wù)棧中有一個此Activity的實例,那么重新啟動Activity就不會創(chuàng)建新的實例崇摄,而且和singleTop一樣擎值,onNewIntent方法會被回調(diào)

4、singleInstance

單實例模式逐抑,這是一種加強的singleTask模式鸠儿,只要有一個任務(wù)棧中有Activity的實例,那么新實例就不會被創(chuàng)建厕氨。換句話說进每,singleInstance的Activity實例只能位于一個任務(wù)棧中。

下面我將用運行實例代碼結(jié)合日志輸出來分析各種啟動模式的區(qū)別

代碼:
LaunchMode應(yīng)用:

package com.android.yanghuaan.launchmode;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class AActivity extends AppCompatActivity {

    private static final String TAG = "Activity_A";

    @Override
    protected void onRestart() {
        Log.d(TAG, "restarted.");
        super.onRestart();
    }

    @Override
    protected void onStart() {
        Log.d(TAG, "started.");
        super.onStart();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "created.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        findViewById(R.id.start_B_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), BActivity.class);
                startActivity(intent);

            }
        });
        findViewById(R.id.start_A_self_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), AActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onNewIntent(Intent intent) {
        Log.d(TAG, "new intent");
        super.onNewIntent(intent);
    }

    @Override
    protected void onResume() {
        Log.d(TAG, "resumed.");
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "destroyed.");
        super.onDestroy();
    }
}
package com.android.yanghuaan.launchmode;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class BActivity extends AppCompatActivity {

    private static final String TAG = "Activity_B";

    @Override
    protected void onRestart() {
        Log.d(TAG, "restarted.");
        super.onRestart();
    }

    @Override
    protected void onStart() {
        Log.d(TAG, "started.");
        super.onStart();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "created.");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_b);
        findViewById(R.id.start_A_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), AActivity.class);
                startActivity(intent);

            }
        });
        findViewById(R.id.start_B_self_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getApplicationContext(), BActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onResume() {
        Log.d(TAG, "resumed.");
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        Log.d(TAG, "destroyed.");
        super.onDestroy();
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.yanghuaan.launchmode">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--主要在activity中改變啟動模式命斧,不同啟動模式下此處代碼不同-->
        <activity
            android:name=".AActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>
    </application>
</manifest>

LaunchMode應(yīng)用包含兩個Activity--A和B田晚,每個Activity都有兩個按鈕,一個用來啟動自己国葬,另一個用來啟動另一個Activity贤徒。
LaunchMode2代碼:

package com.android.yanghuaan.launchmode2;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.start_other_activity_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClassName("com.android.yanghuaan.launchmode",
                        "com.android.yanghuaan.launchmode.AActivity");
                startActivity(intent);
            }
        });
    }
}

LaunchMode2應(yīng)用包含一個Activity,它可以用來啟動LaunchMode應(yīng)用的一個Activity汇四。只有在singleInstance的例子中才使用到LaunchMode2應(yīng)用接奈,因此寫好只需跑一次、將LaunchMode2安裝到安卓手機上即可通孽。

通過在Activity的生命周期方法中添加輸出日志的代碼來追蹤每個Activity的活動

standard 模式

<activity
            android:name=".AActivity"
            android:launchMode="standard">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步驟:
??進入LaunchMode應(yīng)用后點擊兩次啟動自己的按鈕
日志輸出:

06-13 20:25:07.982 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:08.201 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:25:11.399 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:11.422 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:11.423 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:25:14.589 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:25:14.614 18980-18980/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
??從日志可以看出序宦,onCreate->onStart->onResume被被調(diào)用了3次,說明創(chuàng)建了3個AActivity的實例背苦,即Activity實例被重復創(chuàng)建了互捌。此時需要3次按back才能返回桌面

singleTop 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity"
            android:launchMode="singleTop">
        </activity>

操作步驟:
??進入LaunchMode應(yīng)用后先按啟動BActivity的按鈕潘明,此時進入了BActivity;再按啟動AActivity的按鈕秕噪,此時進入了AActivity钳降;再按兩次啟動自己(AActivity)的按鈕
日志輸出:

06-13 20:35:07.446 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:07.483 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:10.828 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: created.
06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:35:10.860 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:35:12.033 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:12.068 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:35:16.913 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:19.872 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:35:19.873 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: restarted.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:35:24.084 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:35:24.394 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:35:24.951 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:35:25.252 4080-4080/com.android.yanghuaan.launchmode D/Activity_B: destroyed.
06-13 20:35:27.292 4080-4080/com.android.yanghuaan.launchmode D/Activity_A: destroyed.

分析:
??從AActivity到BActivity,再啟動AActivity巢价,發(fā)現(xiàn)onCreate被調(diào)用,即表明AActivity實例被重新創(chuàng)建固阁;根據(jù)棧的特點可知此時AActivity的實例并沒有位于棧頂壤躲,所以AActivity實例被重新創(chuàng)建;
??返回AActivity后备燃,再次啟動兩次AActivity都發(fā)現(xiàn)只有onResume和onNewIntent被調(diào)用碉克,可知AActivity的實例被重新使用,并沒有創(chuàng)建新的實例并齐,這兩次創(chuàng)建Activity的過程中AActivity的實例都位于棧頂漏麦,所以沒有重新創(chuàng)建。
??此時連續(xù)按back鍵的效果是:BActivity->AActivity->桌面况褪;

singleTask 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步驟:
??進入LaunchMode應(yīng)用撕贞,按啟動BActivity的按鈕啟動BActivity,再按啟動AActivity的按鈕啟動AActivity
日志輸出:

06-13 20:47:26.429 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:47:26.429 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:47:28.458 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:47:28.459 32534-32534/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:47:28.780 32534-32534/com.android.yanghuaan.launchmode D/Activity_B: destroyed.

分析:
??從BActivity啟動AActivity测垛,發(fā)現(xiàn)onRestart被調(diào)用捏膨,同時onNewIntent也被調(diào)用,表明AActivity的實例并沒有被重新創(chuàng)建食侮;此時只需按一次back鍵就可以返回桌面号涯,因為在從BActivity創(chuàng)建AActivity的過程中BActivity被出棧了。

singleInstance 模式

<activity
            android:name=".AActivity"
            android:launchMode="singleInstance"
            android:allowTaskReparenting="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".BActivity">
        </activity>

操作步驟:
??先啟動應(yīng)用LuanchMode锯七,再按啟動BActivity的按鈕啟動BActivity链快;然后通過 home鍵返回桌面,啟動LaunchMode2應(yīng)用眉尸,在里面按啟動其他應(yīng)用Activity的按鈕啟動AActivity域蜗;最后通過 home鍵返回桌面,啟動LaunchMode應(yīng)用
日志輸出:

06-13 20:55:40.044 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: created.
06-13 20:55:40.136 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:55:40.137 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:55:41.046 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: created.
06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: started.
06-13 20:55:41.079 21024-21024/com.android.yanghuaan.launchmode D/Activity_B: resumed.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:55:49.998 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.
06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: new intent
06-13 20:56:00.336 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: restarted.
06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: started.
06-13 20:56:00.337 21024-21024/com.android.yanghuaan.launchmode D/Activity_A: resumed.

分析:
??從LaunchMode2啟動AActivity噪猾,發(fā)現(xiàn)AActivity并沒有被重新創(chuàng)建地消,而是調(diào)用了onNewIntent和onRestart,并且重新從桌面進入LaunchMode應(yīng)用也是如此畏妖,看起來就像AActivity從一個任務(wù)棧中移動到另一個任務(wù)棧中脉执,這充分說明了singleInstance模式的Activity只能存在于一個任務(wù)棧中。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末戒劫,一起剝皮案震驚了整個濱河市半夷,隨后出現(xiàn)的幾起案子婆廊,更是在濱河造成了極大的恐慌,老刑警劉巖巫橄,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淘邻,死亡現(xiàn)場離奇詭異,居然都是意外死亡湘换,警方通過查閱死者的電腦和手機宾舅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彩倚,“玉大人筹我,你說我怎么就攤上這事》耄” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長猜扮。 經(jīng)常有香客問我压储,道長孕似,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任翘紊,我火速辦了婚禮宇立,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好涩馆,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布鲜结。 她就那樣靜靜地躺著蔗候,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锈遥。 梳的紋絲不亂的頭發(fā)上纫事,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音所灸,去河邊找鬼丽惶。 笑死,一個胖子當著我的面吹牛爬立,可吹牛的內(nèi)容都是我干的钾唬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼知纷!你這毒婦竟也來了壤圃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤琅轧,失蹤者是張志新(化名)和其女友劉穎伍绳,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乍桂,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡冲杀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了睹酌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片权谁。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖憋沿,靈堂內(nèi)的尸體忽然破棺而出旺芽,到底是詐尸還是另有隱情,我是刑警寧澤辐啄,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布采章,位于F島的核電站,受9級特大地震影響壶辜,放射性物質(zhì)發(fā)生泄漏悯舟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一砸民、第九天 我趴在偏房一處隱蔽的房頂上張望抵怎。 院中可真熱鬧,春花似錦岭参、人聲如沸反惕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姿染。三九已至,卻和暖如春蚌本,著一層夾襖步出監(jiān)牢的瞬間盔粹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工程癌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留舷嗡,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓嵌莉,卻偏偏與公主長得像进萄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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

  • 任務(wù)和返回棧 應(yīng)用通常包含多個Activity中鼠。每個 Activity 均應(yīng)圍繞用戶可以執(zhí)行的特定操作設(shè)計可婶,并且能...
    xinlingzhiyi閱讀 672評論 0 6
  • 一個應(yīng)用程序當中通常都會包含很多個Activity,每個Activity都是一個具有特定的功能援雇,并且可以讓用戶進行...
    尹star閱讀 27,979評論 46 306
  • 在Android應(yīng)用中, Activity是最核心的組件, 如何生成一個Activity實例, 可以選擇不同的啟動...
    pyx0225閱讀 438評論 0 0
  • 任務(wù)棧是什么任務(wù)棧Task矛渴,是一種用來放置Activity實例的容器,他是以棧的形式進行盛放惫搏,也就是所謂的先進后出...
    Jason_andy閱讀 460評論 0 1
  • 喂具温,女孩。 那個笑中有柔情筐赔, 住在小鎮(zhèn)盡頭的女孩铣猩。 對, 是在叫你茴丰。 還記得我嗎达皿? 無論你是否記得, 在某幾個流浪...
    Wallace_QIAN閱讀 249評論 0 1