Activity生命周期和啟動模式理解

一、生命周期

1.正常情況下生命周期分析

activity_lifecycle.png

完整生命周期:onCreate -> onDestroy
可見生命周期:onStart -> onStop
前臺生命周期: onResume -> onPause

2.常見生命周期的區(qū)別

1. onCreate 和 onStart

(1)可見與不可見的區(qū)別逼肯。前者不可見犀勒,后者可見聘殖。
(2)onCreate方法只在Activity創(chuàng)建時執(zhí)行一次,而onStart方法在Activity的切換以及按Home鍵返回桌面再切回應(yīng)用的過程中被多次調(diào)用。

2.onStart 和 onRestart

如果一個activity第一次創(chuàng)建,那么只會走onStart军俊,如果是切換應(yīng)用或者桌面,那么就會走onRestart
If it's destroyed onCreate(.) > onStart(.) > onResume(.) is called(variables are lost, redraw).
If it's stopped onRestart(.) > onStart(.) > onResume(.) is called(variables are not lost, redraw)

3.onStart 和 onResume

onStart activity 可見捧存,不在前臺
onResume activity 可見粪躬,前臺且可與用戶交互
這2個的主要區(qū)別就是Activity此時是否可以與用戶交互

4.onPause 和 onStop

這2個狀態(tài)通常是配對執(zhí)行的,
有一種情況是特殊的昔穴,新啟動的Activity是一個透明的界面镰官,那么第一個Activity執(zhí)行onPause后,onStop是不會調(diào)用的

<activity android:name=".SecondActivity"
    android:theme="@style/Theme.AppCompat.Dialog" />

5.onStop & onDestroy

onStop階段Activity還沒有被銷毀吗货,對象還在內(nèi)存中朋魔,此時可以通過切換Activity再次回到該Activity,而onDestroy階段Activity被銷毀

tips:

不同的生命周期適合不同的資源初始化或者釋放工作卿操,實(shí)踐和工作中多總結(jié)警检。http://www.reibang.com/p/fb44584daee3

3.常見操作的生命周期

1.Launcher點(diǎn)擊啟動

01-16 10:57:22.429 26845-26845/? I/ActivityLife: onCreate...
01-16 10:57:22.429 26845-26845/? I/ActivityLife: onStart...
01-16 10:57:22.429 26845-26845/? I/ActivityLife: onResume...

2.back鍵退出

01-16 10:58:58.139 26845-26845/? I/ActivityLife: onPause...
01-16 10:58:58.459 26845-26845/? I/ActivityLife: onStop...
01-16 10:58:58.459 26845-26845/? I/ActivityLife: onDestroy...

3.HOME鍵退出然后再次點(diǎn)擊啟動

01-16 10:59:49.019 26845-26845/? I/ActivityLife: onPause...
01-16 10:59:49.309 26845-26845/? I/ActivityLife: onStop...
01-16 11:00:06.519 26845-26845/? I/ActivityLife: onRestart...
01-16 11:00:06.519 26845-26845/? I/ActivityLife: onStart...
01-16 11:00:06.519 26845-26845/? I/ActivityLife: onResume...

4.鎖屏解鎖

01-16 11:02:33.739 26845-26845/? I/ActivityLife: onPause...
01-16 11:02:33.779 26845-26845/? I/ActivityLife: onStop...
01-16 11:02:35.509 26845-26845/? I/ActivityLife: onRestart...
01-16 11:02:35.529 26845-26845/? I/ActivityLife: onStart...
01-16 11:02:35.529 26845-26845/? I/ActivityLife: onResume...

2.異常情況下的生命周期分析

1.觸發(fā)情況:

1.系統(tǒng)資源相關(guān)的配置發(fā)生變化導(dǎo)致Activity被殺死和重建
2.系統(tǒng)內(nèi)存資源不足,lmk

2.執(zhí)行的特殊生命周期:

onSaveInstanceState & onRestoreInstanceState

1.onSaveInstanceState 通常在onStop之前害淤,用于保存Activity數(shù)據(jù)
2.onRestoreInstanceState 通常在onStart之后扇雕,恢復(fù)Activity數(shù)據(jù)

tips:

在onCreate和onRestoreInstanceState中都有一個參數(shù)savedInstanceState,二者的區(qū)別是:onRestoreInstanceState的參數(shù)是一定有值的窥摄,我們不用額外的判斷它是否為空镶奉,但是onCreate不行,onCreate如果正常啟動的話崭放,savedInstanceState的值是null

3.典型示例哨苛,系統(tǒng)配置變化,屏幕旋轉(zhuǎn)

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "ActivityLife";

    private static final String EDIT_TAG = "edit_tag";
    private EditText editText;

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.i(TAG, "onSaveInstanceState...");
        super.onSaveInstanceState(outState);
        String s = editText.getText().toString();
        outState.putString(EDIT_TAG,s);
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.i(TAG, "onRestoreInstanceState...");
        //onCreate 或者這里恢復(fù)數(shù)據(jù)均可
        editText.setText(savedInstanceState.getString(EDIT_TAG));
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.i(TAG, "onCreate...");
        editText = (EditText) findViewById(R.id.edit_content);
        if (savedInstanceState != null){
            Log.i(TAG, "onCreate savedInstanceState is not null");
            editText.setText(savedInstanceState.getString(EDIT_TAG));
        }
    }
}

從Lanucher啟動并且旋轉(zhuǎn)一次屏幕币砂,生命周期如下:

01-16 11:59:30.459 29726-29726/? I/ActivityLife: onCreate...
01-16 11:59:30.459 29726-29726/? I/ActivityLife: onStart...
01-16 11:59:30.459 29726-29726/? I/ActivityLife: onResume...
01-16 11:59:38.609 29726-29726/? I/ActivityLife: onPause...
01-16 11:59:38.609 29726-29726/? I/ActivityLife: onSaveInstanceState...
01-16 11:59:38.619 29726-29726/? I/ActivityLife: onStop...
01-16 11:59:38.619 29726-29726/? I/ActivityLife: onDestroy...
01-16 11:59:38.669 29726-29726/? I/ActivityLife: onCreate...
01-16 11:59:38.669 29726-29726/? I/ActivityLife: onCreate savedInstanceState is not null
01-16 11:59:38.669 29726-29726/? I/ActivityLife: onStart...
01-16 11:59:38.669 29726-29726/? I/ActivityLife: onRestoreInstanceState...
01-16 11:59:38.669 29726-29726/? I/ActivityLife: onResume...

4.onConfigurationChanged

當(dāng)系統(tǒng)配置發(fā)生變化建峭,如果不希望Activity重新創(chuàng)建,可以在AndroidManifest文件中給Activity加上屬性决摧,以屏幕旋轉(zhuǎn)為例

android:configChanges="orientation|screenSize"

注意:從 Android 3.2(API 級別 13)開始亿蒸,當(dāng)設(shè)備在縱向和橫向之間切換時凑兰,“屏幕尺寸”也會發(fā)生變化。因此边锁,在開發(fā)針對 API 級別 13 或更高版本(正如 minSdkVersion 和 targetSdkVersion 屬性中所聲明)的應(yīng)用時姑食,若要避免由于設(shè)備方向改變而導(dǎo)致運(yùn)行時重啟,則除了 "orientation" 值以外茅坛,您還必須添加 "screenSize" 值音半。 也就是說,您必須聲明 android:configChanges="orientation|screenSize"贡蓖。

configChanges相關(guān)屬性

config_changes.PNG

二曹鸠、Activity的啟動模式

1.Activity的四種啟動模式

standard:標(biāo)準(zhǔn)模式,每次啟動一個Activity都會重新創(chuàng)建一個新的實(shí)例摩梧,不管這個實(shí)例是否已經(jīng)存在
singleTop:棧頂復(fù)用模式物延,如果新的Activity已經(jīng)位于任務(wù)棧的棧頂宣旱,那么此Activity就不會被重新創(chuàng)建,同時他的onNewIntent方法會被回調(diào)
singleTask:棧內(nèi)復(fù)用模式仅父,如果一個Activity在一個任務(wù)棧內(nèi)存在,那么多次啟動這個Activity都不會重新創(chuàng)建實(shí)例浑吟,它的onNewIntent方法也會被回調(diào)
singleInstance:單實(shí)例模式笙纤,具有此種模式的Activity只能單獨(dú)的位于一個任務(wù)棧中

standard 和 singleTop都比較好理解,下面主要分析下singleTask和singleInstance的特點(diǎn)组力。會用到的調(diào)試命令:

adb shell dumpsys activity | grep com.example.sven.activitydemo

2.singleTask的特點(diǎn)

1.singleTask 和 taskAffinity

1.launchMode=singleTask 的應(yīng)用啟動時是否會創(chuàng)建新的任務(wù)和taskAffinity屬性有關(guān)

設(shè)置了"singleTask"啟動模式的Activity省容,它在啟動的時候,會先在系統(tǒng)中查找屬性值affinity等于它的屬值taskAffinity的任務(wù)存在燎字;如果存在這樣的任務(wù)腥椒,它就會在這個任務(wù)中啟動,否則就會在新任務(wù)中啟動候衍。因此如果我們想要設(shè)置了"singleTask"啟動模式的Activity在新的任務(wù)中啟動笼蛛,就要為它設(shè)置一個唯一的taskAffinity屬性值。

示例:A應(yīng)用中蛉鹿,A0(表示啟動界面滨砍,A1跳轉(zhuǎn)的第二個界面,依次類推)A0-A1
(1)設(shè)置SecondActivity launchMode="singleTask"妖异,但不指定taskAffinity

TaskRecord{576dbde #53 A=com.example.sven.activitydemo U=0 sz=2}
    Run #5: ActivityRecord{dc04be8 u0 com.example.sven.activitydemo/.SecondActivity t53}
    Run #4: ActivityRecord{bebf9d2 u0 com.example.sven.activitydemo/.MainActivity t53}

可以看到惋戏,雖然設(shè)置了singleTask的lanuchModel,但是MainActivity和SecondActivity還是在同一個任務(wù)棧中

(2)設(shè)置SecondActivity launchMode="singleTask" 他膳,同時指定taskAffinity = "com.example.sven.activitydemo.second"

TaskRecord{705495 #55 A=com.example.sven.activitydemo.second U=0 sz=1}
    Run #5: ActivityRecord{5a9b163 u0 com.example.sven.activitydemo/.SecondActivity t55}
TaskRecord{9d799aa #54 A=com.example.sven.activitydemo U=0 sz=1}
    Run #4: ActivityRecord{5e9adf5 u0 com.example.sven.activitydemo/.MainActivity t54}

可以看到响逢,設(shè)置了taskAffinity后,新的Activity就運(yùn)行在新的任務(wù)棧里了

tips:

默認(rèn)情況下棕孙,所有Activity的所需任務(wù)棧名均為包名龄句,所以說如果將上面的taskAffinity屬性設(shè)置為包名回论,SecondActivity也是不會在新的任務(wù)棧中啟動的

2.在同一個任務(wù)棧中具有唯一性
如果設(shè)置了"singleTask"啟動模式的Activity不是在新的任務(wù)中啟動時,它會在已有的任務(wù)中查看是否已經(jīng)存在對應(yīng)的Activity實(shí)例分歇,如果存在傀蓉,就會把位于這個Activity實(shí)例上面的Activity全部結(jié)束掉,最終這個Activity實(shí)例位于任務(wù)的堆棧頂端中职抡。
示例:
MainActity SecondActivty ThirdActivty(以上3個Activity用A葬燎、B、C代表)在2種條件下執(zhí)行如下過程 A -> B ->C -> A ->B

(1) SecondActivty launchMode="singleTask"缚甩,taskAffinity=包名谱净,最終棧中的結(jié)果如下

TaskRecord{8d620aa #62 A=com.example.sven.activitydemo U=0 sz=2}
    Run #5: ActivityRecord{ab051c1 u0 com.example.sven.activitydemo/.SecondActivity t62}
    Run #4: ActivityRecord{56fcc63 u0 com.example.sven.activitydemo/.MainActivity t62}

(2) 設(shè)置SecondActivty 指定 taskAffinity = "com.example.sven.activitydemo.second"

  TaskRecord{4e4a3bc #61 A=com.example.sven.activitydemo.second U=0 sz=1}
    Run #5: ActivityRecord{f48dc2b u0 com.example.sven.activitydemo/.SecondActivity t61}
  TaskRecord{ea52f45 #60 A=com.example.sven.activitydemo U=0 sz=1}
    Run #4: ActivityRecord{9e4ab1 u0 com.example.sven.activitydemo/.MainActivity t60}

可以看到在2種情況下, 不論是否設(shè)定taskAffinity擅威,在SecondActivity棧頂?shù)膶?shí)例都被清掉了

3.任務(wù)(Task)不僅可以跨應(yīng)用(Application)壕探,還可以跨進(jìn)程(Process)

示例:
2個應(yīng)用中A,B中,2個ActivityA1,B1的singleTask的Activity的taskAffinity設(shè)置為相同郊丛,執(zhí)行如下過程 A0->A1李请,B0->B1

android:launchMode="singleTask"
android:taskAffinity="com.example.sven.activitydemo.second"

TaskRecord{a412e6e #71 A=com.example.sven.activitydemo.second U=0 sz=2}
    Run #5: ActivityRecord{12bc505 u0 com.example.sven.activitydemo2/.SecondActivityCopy t71}
  TaskRecord{fa790f #72 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #4: ActivityRecord{2610bd9 u0 com.example.sven.activitydemo2/.MainActivityCopy t72}
  TaskRecord{a412e6e #71 A=com.example.sven.activitydemo.second U=0 sz=2}
    Run #3: ActivityRecord{ca0064a u0 com.example.sven.activitydemo/.SecondActivity t71}
  TaskRecord{c224d9c #70 A=com.example.sven.activitydemo U=0 sz=1}
    Run #2: ActivityRecord{4257b8e u0 com.example.sven.activitydemo/.MainActivity t70}

可以看到相同taskAffinity的Run#5和Run#3是在同一個任務(wù)棧a412e6e中的。

tips:

Application厉熟,Task和Process的區(qū)別與聯(lián)系
application翻譯成中文時一般稱為“應(yīng)用”或“應(yīng)用程序”导盅,在android中,總體來說一個應(yīng)用就是一組組件的集合揍瑟。
task是在程序運(yùn)行時白翻,只針對activity的概念。說白了绢片,task是一組相互關(guān)聯(lián)的activity的集合滤馍,它是存在于framework層的一個概念,控制界面的跳轉(zhuǎn)和返回底循。這個task存在于一個稱為backstack的數(shù)據(jù)結(jié)構(gòu)中巢株,也就是說,framework是以棧的形式管理用戶開啟的activity此叠。這個棧的基本行為是纯续,當(dāng)用戶在多個activity之間跳轉(zhuǎn)時,執(zhí)行壓棧操作灭袁,當(dāng)用戶按返回鍵時猬错,執(zhí)行出棧操作。
process一般翻譯成進(jìn)程茸歧,進(jìn)程是操作系統(tǒng)內(nèi)核中的一個概念倦炒,表示直接受內(nèi)核調(diào)度的執(zhí)行單位。在應(yīng)用程序的角度看软瞎,我們用java編寫的應(yīng)用程序逢唤,運(yùn)行在dalvik虛擬機(jī)中拉讯,可以認(rèn)為一個運(yùn)行中的dalvik虛擬機(jī)實(shí)例占有一個進(jìn)程,所以鳖藕,在默認(rèn)情況下魔慷,一個應(yīng)用程序的所有組件運(yùn)行在同一個進(jìn)程中。但是這種情況也有例外著恩,即院尔,應(yīng)用程序中的不同組件可以運(yùn)行在不同的進(jìn)程中。只需要在manifest中用process屬性指定組件所運(yùn)行的進(jìn)程的名字喉誊。如下所示:

 <activity
        android:name=".SecondActivityCopy"
       android:process=":remote"
        android:allowTaskReparenting="true" />

4.allowTaskReparenting
一個應(yīng)用A啟動另一個應(yīng)用B的B1(standard模式)Activity邀摆,如果這個Activity的allowTaskReparenting屬性為true的話,那么B啟動后B1直接會轉(zhuǎn)移到B的任務(wù)棧中∥榍眩現(xiàn)象就是A啟動B1栋盹,在啟動B時,顯示的就是B1敷矫,而不是B0

A -> B1:

TaskRecord{fc84b0d #46 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #1: ActivityRecord{8ebbcf3 u0 com.example.sven.activitydemo2/.SecondActivityCopy t46}
  TaskRecord{137b068 #45 A=com.example.sven.activitydemo U=0 sz=1}
    Run #0: ActivityRecord{b7827ad u0 com.example.sven.activitydemo/.MainActivity t45}


啟動B
TaskRecord{fc84b0d #46 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #1: ActivityRecord{8ebbcf3 u0 com.example.sven.activitydemo2/.SecondActivityCopy t46}
  TaskRecord{137b068 #45 A=com.example.sven.activitydemo U=0 sz=1}
    Run #0: ActivityRecord{b7827ad u0 com.example.sven.activitydemo/.MainActivity t45}

4.SingleInstance的特點(diǎn)

1.singleInstance模式啟動的Activity具有全局唯一性
整個系統(tǒng)中只會存在一個這樣的實(shí)例例获,如果在啟動這樣的Activity時,已經(jīng)存在了一個實(shí)例沪饺,那么會把它所在的任務(wù)調(diào)度到前臺躏敢,重用這個實(shí)例闷愤。

示例:
2 個應(yīng)用A整葡,B,設(shè)置B1 launchMode="singleInstance"讥脐, 執(zhí)行如下過程遭居,先B -> B1, 再A0 ->B1

TaskRecord{9b9bb06 #108 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #3: ActivityRecord{5520232 u0 com.example.sven.activitydemo2/.SecondActivityCopy t108}
TaskRecord{7b4a5c7 #107 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #2: ActivityRecord{6cf92f7 u0 com.example.sven.activitydemo2/.MainActivityCopy t107}

TaskRecord{9b9bb06 #108 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #4: ActivityRecord{5520232 u0 com.example.sven.activitydemo2/.SecondActivityCopy t108}
TaskRecord{3cccdb5 #109 A=com.example.sven.activitydemo U=0 sz=1}
    Run #3: ActivityRecord{facfdb u0 com.example.sven.activitydemo/.MainActivity t109}
TaskRecord{7b4a5c7 #107 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #2: ActivityRecord{6cf92f7 u0 com.example.sven.activitydemo2/.MainActivityCopy t107}

可以看到 2 個過程中B1 的Taskrecord沒有發(fā)生變化

2.singleInstance模式啟動的Activity具有獨(dú)占性
它會獨(dú)自占用一個任務(wù)旬渠,被他開啟的任何activity都會運(yùn)行在其他任務(wù)中俱萍,但是否能夠開啟一個新任務(wù),要看當(dāng)前系統(tǒng)中是不是已經(jīng)有了一個和要開啟的Activity的taskAffinity屬性相同的任務(wù)告丢。
示例:
B0->B1 B1->A3(B0和B1又因?yàn)樯蟼€原則枪蘑,所以是在不同的任務(wù)棧中)

  TaskRecord{94de3cf #69 A=com.example.sven.activitydemo U=0 sz=1}
    Run #2: ActivityRecord{89ba288 u0 com.example.sven.activitydemo/.ThirdActivity t69}
  TaskRecord{2ad415c #68 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #1: ActivityRecord{73d6ca u0 com.example.sven.activitydemo2/.SecondActivityCopy t68}
  TaskRecord{6d70c65 #67 A=com.example.sven.activitydemo2 U=0 sz=1}
    Run #0: ActivityRecord{3941c44 u0 com.example.sven.activitydemo2/.MainActivityCopy t67}

先啟動A0(A3和A0是運(yùn)行在同一個棧中) B0->B1 B1->A3

TaskRecord{5db49f9 #71 A=com.example.sven.activitydemo U=0 sz=2}
  Run #3: ActivityRecord{dfea174 u0 com.example.sven.activitydemo/.ThirdActivity t71}
TaskRecord{e7e8d3e #73 A=com.example.sven.activitydemo2 U=0 sz=1}
  Run #2: ActivityRecord{cb12857 u0 com.example.sven.activitydemo2/.SecondActivityCopy t73}
TaskRecord{3f750ec #72 A=com.example.sven.activitydemo2 U=0 sz=1}
  Run #1: ActivityRecord{2efad8b u0 com.example.sven.activitydemo2/.MainActivityCopy t72}
TaskRecord{5db49f9 #71 A=com.example.sven.activitydemo U=0 sz=2}
  Run #0: ActivityRecord{c39fdab u0 com.example.sven.activitydemo/.MainActivity t71}

可以看到A3(Run #2)會在A0 (Run #5)的任務(wù)棧中46bac8a

tips:

啟動時是否開啟任務(wù)棧,考慮3個點(diǎn):1.被啟動的Activity的launchModel岖免,如果是singleTask要同時考慮它的taskAffinity
2.啟動Activity的launchmode(singleInstance)
3.當(dāng)前是否有被啟動應(yīng)用的任務(wù)棧

4.Activity的flag

1.Intent.FLAG_ACTIVITY_NEW_TASK

等價(jià)于 launchMode = singleTask

2.Intent.FLAG_ACTIVITY_SINGLE_TOP

等價(jià)于 launchMode = singleTop 設(shè)置singleTop 和一起使用taskAffinity 岳颇,只有singleTop的效果

3.Intent.FLAG_ACTIVITY_CLEAR_TOP

檢查目標(biāo)棧中是否有對應(yīng)的實(shí)例,如果有就會將該實(shí)例之上的所有棧都清掉
A-B(正常啟動)->C->A->B(clearTop方式啟動)
(1) B的launchmode 是standard

TaskRecord{fec37c7 #134 A=com.example.sven.activitydemo U=0 sz=4}
    Run #5: ActivityRecord{91e286b u0 com.example.sven.activitydemo/.MainActivity t134}
    Run #4: ActivityRecord{775d8ae u0 com.example.sven.activitydemo/.ThirdActivity t134}
    Run #3: ActivityRecord{20304d6 u0 com.example.sven.activitydemo/.SecondActivity t134}
    Run #2: ActivityRecord{b049afa u0 com.example.sven.activitydemo/.MainActivity t134}

TaskRecord{fec37c7 #134 A=com.example.sven.activitydemo U=0 sz=2}
   Run #3: ActivityRecord{4fdc1db u0 com.example.sven.activitydemo/.SecondActivity t134}
    Run #2: ActivityRecord{b049afa u0 com.example.sven.activitydemo/.MainActivity t134}

可以看到颅湘,如果被啟動的SecondActivity的啟動模式是standard话侧,那么B會重新創(chuàng)建新的實(shí)例并且之前的實(shí)例及實(shí)例之上的Activity都會出棧

(2) B的launchmode是singleTask

TaskRecord{249ecaa #135 A=com.example.sven.activitydemo U=0 sz=4}
    Run #5: ActivityRecord{1116cb u0 com.example.sven.activitydemo/.MainActivity t135}
    Run #4: ActivityRecord{92b068e u0 com.example.sven.activitydemo/.ThirdActivity t135}
    Run #3: ActivityRecord{96bd6b6 u0 com.example.sven.activitydemo/.SecondActivity t135}
    Run #2: ActivityRecord{44bf730 u0 com.example.sven.activitydemo/.MainActivity t135}

TaskRecord{249ecaa #135 A=com.example.sven.activitydemo U=0 sz=2}
    Run #3: ActivityRecord{96bd6b6 u0 com.example.sven.activitydemo/.SecondActivity t135}
    Run #2: ActivityRecord{44bf730 u0 com.example.sven.activitydemo/.MainActivity t135}

可以看到,如果被啟動的SecondActivity的啟動模式是SingleTask闯参,那么B會清除實(shí)例之上的Activity瞻鹏,并且調(diào)用onNewIntent方法

總結(jié):主要2個點(diǎn)悲立,清除被啟動Activity之上的實(shí)例,是否創(chuàng)建新的實(shí)例和被啟動Activity的lanuchMode有關(guān)

4. Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

具有這個標(biāo)記的Activity不會出現(xiàn)在歷史Activity的記錄中新博,和android:excludeFromRecents作用相同

tips:啟動模式有2種設(shè)置方法薪夕,通過設(shè)置Intent的FLAG 和 AndroidManifest.xml ,第一種方式的優(yōu)先級大于第二種方式

三赫悄、IntentFilter的匹配規(guī)則

Activity的顯示調(diào)用和隱式調(diào)用:http://blog.csdn.net/xiao__gui/article/details/11392987

一個activity可以有多個過濾器寥殖,每個過濾器均可以有多個action,category和data

1.action的匹配規(guī)則

Intent 中的 action 只要有一個與過濾器(manifest中的intent-filter)的匹配涩蜘,就可調(diào)用這個過濾器所在的組件嚼贡。

2.category的匹配規(guī)則

category 表示類別,最常見就是這2個

<category android:name="android.intent.category.LAUNCHER" />
 <category android:name="android.intent.category.DEFAULT" />

1. 隱式啟動時intent會自動的添加一個默認(rèn)的category同诫,所以隱式啟動時粤策,過濾器中的默認(rèn)的category必須要加

 <category android:name="android.intent.category.DEFAULT"/>

2. 隱式啟動時,intent中添加的category必須包含在過濾器中

3.data的匹配規(guī)則

data 表示該組件可以支持的數(shù)據(jù)格式與類型误窖,intent 至少可以匹配過濾器中的一個

主要由兩部分組成:1.mimeType 2.URI 叮盘,語法如下:

<data android:scheme="string"
    android:host="string"
    android:port="string"
    android:path="string"
    android:pathPattern="string"
    android:pathPrefix="string"
    android:mimeType="string" />

(1) mimeType 指的是支持的數(shù)據(jù)類型與格式
常見的有:1.text/plain 2.image/jpeg 3.video/* 4.audio/*
/ 號前面的是數(shù)據(jù)類型,后面是具體格式霹俺。

(2) URI 格式:

<scheme>://<host>:<port>/[<path>]|[<pathPrefix>]|[pathPattern]

1.scheme柔吼、host、port丙唧、path分別表示URI的模式愈魏、主機(jī)名和端口號和路徑

例如:http://www.baidu.com:80/search/info

2.如果scheme或者h(yuǎn)ost未指定那么URI就無效

3.URI 是有默認(rèn)值的,content 和 file想际,這里不是很理解培漏,不過發(fā)現(xiàn)這樣一種情況:

在intent-filter 中添加任意一種mimeType,不指定URI

<data android:mimeType="image/jpeg"/>

intent啟動時胡本,設(shè)置URI為 content:.* 或 file:.* 均可啟動

intent.setDataAndType(Uri.parse("content://abc"), "image/jpeg");

4.data 是有如下2種寫法的牌柄,效果是一樣的

<data android:scheme="file"
      android:host="abc"
      android:mimeType="text/plain"/>

<data android:scheme="file"/>
<data android:host="abc"/>
<data android:mimeType="text/plain"/>

如果一個intent-filter 中有多個data 并且他們的URI均不同,建議用第一種侧甫。

data 的匹配規(guī)則這里只列舉的常用的一部分珊佣,還有些情況類似與如下,也可以匹配到披粟,可以將URI 和MIMETYPE的關(guān)理解為action和category的關(guān)系

<data android:scheme="http" android:host="abc" android:mimeType="text/plain"/>
<data android:scheme="http" android:host="abc2" android:mimeType="image/png"/>

intent.setDataAndType(Uri.parse("http://abc"), "image/png");

只能理解為 URI 和MIMETYPE 其實(shí)類似于 action 和 category的關(guān)系咒锻,采用如下的寫法更能表現(xiàn)兩者的關(guān)系,具體大家在實(shí)踐中多多理解

  <data android:scheme="file" android:host="abc" />
  <data android:scheme="file" android:host="abc2" />
  <data android:mimeType="text/plain" />
  <data android:mimeType="image/png" />

tips:

1.如果要為Intent指定完整的data僻爽,必須要調(diào)用setDataAndType方法虫碉,不能先調(diào)用setData然后調(diào)用setType,因?yàn)檫@兩個方法會彼此清除對方的值胸梆。
2.當(dāng)我們啟動Activity可以通過resolveActivity判斷是否有對應(yīng)的Activity

if(this.getPackageManager().resolveActivity(intent, 0) != null){
    startActivity(intent);
}

3.特殊的一組action和category敦捧,標(biāo)記應(yīng)用啟動時打開的Activity须板,少了任何一個都沒有意義

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

4.顯示Component調(diào)用也是可以跨應(yīng)用的,需要顯示指定Activity屬性 android:exported="true" 或者添加一個intent-Filter兢卵,否則會報(bào)AndroidRuntime異常习瑰,通過Tip 3是不能檢查出intent是否正常。

以上這些自己寫了個Demo秽荤,方便大家調(diào)試和學(xué)習(xí):
http://download.csdn.net/detail/time_traveller14/9880456
http://download.csdn.net/detail/time_traveller14/9880457

問題:

  1. onSaveInstanceState 為何會在跳轉(zhuǎn)到別的Activity甜奄、Home鍵以及鎖屏?xí)r調(diào)用?
  2. category 和 data 的更多用法窃款?

參考資料:
https://developer.android.com/reference/android/app/Activity.html
https://developer.android.com/guide/topics/manifest/activity-element.html?hl=zh-cn#config
http://blog.csdn.net/u011240877/article/details/71305797
《Android 開發(fā)藝術(shù)之旅》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末课兄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子晨继,更是在濱河造成了極大的恐慌烟阐,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紊扬,死亡現(xiàn)場離奇詭異蜒茄,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)餐屎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門檀葛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腹缩,你說我怎么就攤上這事屿聋。” “怎么了庆聘?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵胜臊,是天一觀的道長勺卢。 經(jīng)常有香客問我伙判,道長,這世上最難降的妖魔是什么黑忱? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任宴抚,我火速辦了婚禮,結(jié)果婚禮上甫煞,老公的妹妹穿的比我還像新娘菇曲。我一直安慰自己,他們只是感情好抚吠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布常潮。 她就那樣靜靜地躺著,像睡著了一般楷力。 火紅的嫁衣襯著肌膚如雪喊式。 梳的紋絲不亂的頭發(fā)上孵户,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天,我揣著相機(jī)與錄音岔留,去河邊找鬼夏哭。 笑死,一個胖子當(dāng)著我的面吹牛献联,可吹牛的內(nèi)容都是我干的竖配。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼里逆,長吁一口氣:“原來是場噩夢啊……” “哼进胯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起原押,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤龄减,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后班眯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體希停,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年署隘,在試婚紗的時候發(fā)現(xiàn)自己被綠了宠能。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡磁餐,死狀恐怖违崇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情诊霹,我是刑警寧澤羞延,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站脾还,受9級特大地震影響伴箩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鄙漏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一嗤谚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怔蚌,春花似錦巩步、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春竟闪,著一層夾襖步出監(jiān)牢的瞬間声离,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工瘫怜, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留术徊,地道東北人。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓鲸湃,卻偏偏與公主長得像赠涮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子暗挑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

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

  • 一笋除、概述 Activity 作為與用戶交互的一個窗口,是使用非常頻繁的一個基本組件炸裆。Android系統(tǒng)是通過Act...
    三也視界閱讀 2,225評論 3 11
  • 這是我第三遍看《Android開發(fā)藝術(shù)探索》這本書了垃它,從第一遍看的云里霧里,第二遍略微明白之后烹看,我決定看第三遍国拇,并...
    陳添閱讀 854評論 2 8
  • 本章主要學(xué)習(xí)Activity的生命周期和啟動模式以及IntentFilter的匹配規(guī)則分析;其中異常生命周期以及A...
    HuDP閱讀 2,800評論 9 23
  • 對于一個年輕人來說惯殊,一座向往已久的陌生城市就像是一個充滿美好幻想的情婦酱吝,對于段毅來說亦是如此。大學(xué)剛畢業(yè)的他毅然決...
    光趟芍兒閱讀 953評論 2 3
  • 1. 有監(jiān)督學(xué)習(xí)與無監(jiān)督學(xué)習(xí) 前者訓(xùn)練集中的每個數(shù)據(jù)都有正確答案土思,后者反之(聚類) 2. 回歸問題與分類問題 前者...
    神奇的腿閱讀 207評論 0 0