Activity

前言

  • 參考書:Android 開發(fā)藝術(shù)探索

  • 本篇主要介紹 Activity 的生命周期、啟動模式和 Intentfliter 的匹配規(guī)則

正文

一、Activity 的生命周期

分兩種: 正常情況下和異常情況下的生命周期

1.1 正常情況下的生命周期,從上到下
  • onCreate(): 表示 Activity 正在創(chuàng)建,可以做一些初始化工作。

  • onStart(): 表示 Activity 正在啟動,這時 Acticity 已經(jīng)創(chuàng)建出來了,只是沒有出現(xiàn)在前臺,用戶看不到

  • onResume(): 表示 Activity 已經(jīng)可見,可以與用戶進(jìn)行交互

  • onPause(): 表示 Acticity 正在停止,此時可以做一些停止動畫、存儲數(shù)據(jù)等操作,但是注意不能耗時,因?yàn)橹挥羞@個方法執(zhí)行完畢,新的 Activity 的 onResume 才會執(zhí)行

  • onStop(): 表示 Activity 即將停止,可以做一些重量級的回收工作,但是不能耗時

  • onDestroy(): 表示 Activity 即將被銷毀,可以做一些回收工作和資源釋放

還有一個 onRestart() 方法,此方法表示 Activity 正在重新啟動,一般情況下在 Activity 從不可見到可見狀態(tài)的時候,會調(diào)用此方法,比如說 A 跳轉(zhuǎn)到 B 然后再返回 A

1.2 異常情況下的生命周期
1.2.1 資源相關(guān)的系統(tǒng)配置發(fā)生改變導(dǎo)致 Activity 被殺死并重新創(chuàng)建

比如說,橫豎屏切換的時候,顯示的圖片資源及布局文件等系統(tǒng)配置發(fā)生改變,默認(rèn)情況下,Activity 會被銷毀并重新創(chuàng)建,其生命周期方法如下:

  • 首先會調(diào)用 onSaveInstanceState() 方法,做數(shù)據(jù)保存工作,系統(tǒng)默認(rèn)為我們保存當(dāng)前 Activity 的視圖結(jié)構(gòu),并在 Activity 重啟后,為我們恢復(fù)這些數(shù)據(jù),比如 文本框中用戶輸入的數(shù)據(jù),ListView 滾動的位置等,但是如果針對于某個 View 來說,能恢復(fù)什么數(shù)據(jù),可以看 View 的源碼來分析,因?yàn)?View 和 Activity 一樣,都有 onSaveInstanceState() 方法來保存數(shù)據(jù),保存的數(shù)據(jù)在其參數(shù) Bundle 中

  • 其次,調(diào)用 onPause() 、onStop()、onDestory() 方法,注意 onSaveInstanceState() 方法可能在 onPause() 之前調(diào)用,也可能在其之后調(diào)用。

  • 然后,調(diào)用 onCreat() 方法,然后繼續(xù)調(diào)用 onRestoreInstanceState() 方法來為其恢復(fù)狀態(tài)和數(shù)據(jù),我們可以根據(jù)這兩個方法中的參數(shù) Bundle 來判斷此 Activity 是否被重建

1.2.2 資源內(nèi)存不足,導(dǎo)致低優(yōu)先級的 Activity 被殺死

這種方式與上邊的第一種情況保存和恢復(fù)數(shù)據(jù)的方法一致,這里說下 Activity 的優(yōu)先級,從高到低,如下所示:

  • 前臺 Activity ,正在與用戶交互,優(yōu)先級最高

  • 可見,但并非前臺 Activity ,比如 Activity 中彈出一個對話框,導(dǎo)致 Activity 可見,但是無法與用戶交互

  • 后臺 Activity ,已經(jīng)被暫停的 Activity ,比如執(zhí)行了 onStop() 方法,優(yōu)先級最低

另外注意,如果一個進(jìn)程中沒有四大組件運(yùn)行,那么這個進(jìn)程將會很快被殺死!

1.2.3 阻止 Activity 重新創(chuàng)建

在 AndroidMenifest.xml 中為 Activity 添加一條 configChanges 屬性 :

 android:configChanges="orientation"

常用屬性值的含義:

  • locale :設(shè)備的本地位置發(fā)生了改變,一般指切換了系統(tǒng)語言

  • orientation :設(shè)備屏幕發(fā)生改變,比如旋轉(zhuǎn)屏幕

  • keyboardHidden :鍵盤的可訪問性發(fā)生了改變,比如用戶調(diào)出了鍵盤

  • screenSize :屏幕尺寸信息發(fā)生改變,常用于旋轉(zhuǎn)屏幕導(dǎo)致的 尺寸信息改變,一般和 orientation 配合使用

  • smallestScreenSize :表示設(shè)備的物理屏幕尺寸發(fā)生改變,注意指的是物理設(shè)備,跟旋轉(zhuǎn)屏幕沒關(guān)系,比如用戶切換到了外部的顯示設(shè)備,這個不常用。

二、Activity 的啟動模式

2.1 四種啟動模式
  • standard :標(biāo)準(zhǔn)模式,也是系統(tǒng)的默認(rèn)模式,每次啟動一個 Activity 都會創(chuàng)建一個新實(shí)例,不管這個實(shí)例是否存在,會一一放入任務(wù)棧中,然后按回退鍵的時候,會按照先進(jìn)后出的原則,一一退棧!

  • singleTop :棧頂復(fù)用模式,如果新創(chuàng)建的 Activity 已經(jīng)位于任務(wù)棧的棧頂了,那么此 Activity 不會被重建,注意這個 Activity 的 onCreat()、onstart() 方法不會被調(diào)用,因?yàn)樗]有發(fā)生改變,但是會回調(diào) onNewIntent(Intent intent) 方法,從而獲取 intent 信息。

  • singleTask :棧內(nèi)復(fù)用模式,這是一種單實(shí)例模式,只要 Activity 在一個棧中存在,那么多次啟動 Activity 都不會重新創(chuàng)建實(shí)例,和 singleTop 一樣,也會回調(diào)其 onNewIntent(Intent intent) 方法,但是需要注意一點(diǎn),如果棧中有的話,該模式,會把所需要的 Activity 之上的所有 Activity 彈出棧,將需要的這個 Activity 放于棧頂!

  • singleInstance : 它是一種加強(qiáng)版的 singleTask ,它除了具有 singleTask 的所有特性之外,還加強(qiáng)了一點(diǎn),就是只能單獨(dú)的位于一個棧中!一個棧只能有一個 Activity

2.2 為 Activity 指定啟動模式
  • 第一種,通過 AndroidMenifest.xml 文件中,為其添加屬性
android:launchMode="singleTop"
  • 第二種,通過在 Intent 中設(shè)置標(biāo)志位 Flags 來為 Activity 指定模式
Intent intent = new Intent(this,TextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
  • 兩種方式的區(qū)別:
  1. 優(yōu)先級,第二種要高于第一種,兩種都存在的話,以第二種為準(zhǔn);
  2. 限定范圍不同,第一種無法為 Activity 指定 FLAG_ACTIVITY_CLEAR_TOP 標(biāo)識,第二種無法為 Activity 指定 singleInstance 模式!
2.3 Activity 的 Flags

Activity 的 Flags 有很多,作用也很多,有些可以設(shè)定 Activity 的啟動模式,有些可以影響 Acticity 的運(yùn)行狀態(tài),這里記錄些比較常用的 Flags

  • FLAG_ACTIVITY_NEW_TASK ,指定 Activity 的啟動模式為 singleTask

  • FLAG_ACTIVITY_SINGLE_TOP ,指定 Activity 的啟動模式為 singleTop

  • FLAG_ACTIVITY_CLEAR_TOP ,當(dāng) Activity 啟動時,與其在同一個任務(wù)棧并在其上邊的所有 Activity 全部出棧,一般和 singleTask 啟動模式一塊出現(xiàn)

  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ,在某些情況下,我們不希望用戶通過歷史列表回到我們的 Activity 的時候,使用這個標(biāo)記,等同于 xml 文件中的屬性: android:excludeFromRecents="true"

三、Activity 中 IntentFilter 匹配規(guī)則

  • Activity 的啟動方式有兩種,顯式啟動和隱式啟動,如果兩者都存在那么以顯示為主,顯式啟動很簡單,主要記錄下隱式啟動

  • 隱式啟動需要 Intent 能夠匹配目標(biāo)組件的 IntentFilter 中的過濾信息,過濾信息有三個,分別是 action 、 category 、 data,下邊針對這三個過濾信息做介紹

3.1 action 的匹配規(guī)則
  • action 只是一個字符串,區(qū)分大小寫,系統(tǒng)中有預(yù)定義的一些 action 我們也可以自定義自己所需要的 action, action 可以有多個,但是我們只要匹配成功一個即可匹配成功,需要注意的是,只要是隱式啟動,那么 Intent 中必須要有 action
3.2 category 的匹配規(guī)則
  • category 也是一個字符串,category 也可以有多個,但是必須要每個都匹配成功才行,另外,如果需要隱式啟動,那么必須添加 android.intent.category.DEFAULT 這個 category ,因?yàn)槲覀冋{(diào)用 startActivity 方法的時候,系統(tǒng)會默認(rèn)為我們添加這個一個 category ,所以必須要添加
3.3 data 的匹配規(guī)則
  • data 相對復(fù)雜一點(diǎn),結(jié)構(gòu)如下
<data android:scheme="aaa"
 android:host="aaa"
 android:port="aaa"
 android:path="aaa"
 android:pathPattern="aaa"
 android:pathPrefix="aaa"
 android:mimeType="aaa"/>

主要是有兩部分組成 mimeType 和 Uri

  1. mimeType 指媒體類型 例如: image/jpeg vided/* ...
  2. Uri 的結(jié)構(gòu)如下:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

Uri 的屬性介紹如下:

scheme:整個URI的模式,如常見的http,file等,注意如果URI中沒有指定的scheme,那么整個uri無效
host:URI的域名,比如我們常見的www.mi.com,www.baidu.com,與scheme一樣,一旦沒有host那么整個URI也毫無意義;
port:端口號,比如80,很容易理解,只有在URI中指定了scheme和host之后端口號才是有意義的;
path,pathPattern,pathPrefix包含路徑信息,path表示完整的路徑,pathPattern在此基礎(chǔ)上可以包含通配符,pathPrefix表示路徑的前綴信息;
  • 只匹配 scheme 的例子如下:
        <activity android:name=".TextActivity">

            <intent-filter>
                <action android:name="111"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:scheme="222"></data>
            </intent-filter>

        </activity>
        Intent intent = new Intent();
        intent.setAction("111");
        // scheme:// 固定寫法,后邊的 111 是自己隨便寫的
        intent.setData(Uri.parse("222://111"));

        startActivity(intent);
  • 只匹配 mimeType 的例子如下
        <activity android:name=".TextActivity">

            <intent-filter>
                <action android:name="111"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:mimeType="image/*"></data>
            </intent-filter>

        </activity>
        Intent intent = new Intent();
        intent.setAction("111");
        // 這種情況,scheme 默認(rèn)為 content ,親測 file 會報錯
        //注意此處是 setDataAndType 
        intent.setDataAndType(Uri.parse("content://111"),"image/png");
        startActivity(intent);
  • 注意,data,不是必須要添加的,也就是說如果只有 action 和 category 也能匹配成功
  • 還有一點(diǎn),如果我們要啟動系統(tǒng)的頁面,如打電話頁面,需要找到其匹配規(guī)則,進(jìn)行匹配,然后啟動

  • 另外,IntentFilter 可以有多對,只要匹配其中一對即可成功。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Activity 一、四種形態(tài) 運(yùn)行狀態(tài): 當(dāng) Activity 處于棧的頂層,可見,并可與用戶進(jìn)行交互 onRe...
    任教主來也閱讀 1,737評論 1 10
  • 本篇博客是筆者看過《Android開發(fā)藝術(shù)探索》才寫的,有些是借鑒了此本書的內(nèi)容,當(dāng)有些內(nèi)容進(jìn)行了精進(jìn)。 Acti...
    ClAndEllen閱讀 3,477評論 1 27
  • 一、概述 Activity 作為與用戶交互的一個窗口,是使用非常頻繁的一個基本組件。Android系統(tǒng)是通過Act...
    三也視界閱讀 2,269評論 3 11
  • 一本android開發(fā)程序員必讀的一本書,感謝任玉剛大佬的分享 一、Activity的生命周期全面分析 典型情況下...
    kongjn閱讀 563評論 1 3
  • 之所以我聽到別人的一些話生氣,是因?yàn)槟鞘俏乙舱J(rèn)為那人說得對卻一直不想承認(rèn)的軟肋。
    LokieY閱讀 142評論 0 0