Activity的啟動(dòng)模式

待學(xué)的

  • 任務(wù)棧

Activity的 lauchMode

在android系統(tǒng)默認(rèn)狀態(tài)下瘫俊,當(dāng)我們啟動(dòng)activity的時(shí)候,系統(tǒng)會(huì)創(chuàng)建多個(gè)實(shí)例烁巫,并把它們放到一個(gè)任務(wù)棧中巢寡,當(dāng)我們回退的時(shí)候,這些Activity 會(huì)一一回退夸楣。 任務(wù)棧是一個(gè)“先進(jìn)后出”的站結(jié)構(gòu)宾抓,當(dāng)棧中內(nèi)容為空的時(shí)候,系統(tǒng)會(huì)回收這個(gè)任務(wù)棧裕偿。 在創(chuàng)建 activity 的時(shí)候洞慎,有四種啟動(dòng)方式,下面以一一列舉:

  1. standard 標(biāo)準(zhǔn)的啟動(dòng)模式嘿棘,也系統(tǒng)默認(rèn)啟動(dòng)模式劲腿。 每次啟動(dòng)都會(huì)重建一個(gè)新的實(shí)例。它的 onCreate鸟妙、 onStart焦人、onResume 都會(huì)被調(diào)用。
    一個(gè)任務(wù)椫馗福可以有多個(gè)實(shí)例花椭,每個(gè)實(shí)例可以屬于不同的任務(wù)棧。 在這種模式下房午,誰啟動(dòng)了這個(gè)activity矿辽,那么這個(gè)activity就運(yùn)行在誰的任務(wù)棧中。
    當(dāng)使用 ApplicationContext 去啟動(dòng) standard 模式的activity時(shí)候,會(huì)報(bào)錯(cuò)袋倔;
    這是因?yàn)榉?activity 類型的 context 并沒有所謂的任務(wù)棧雕蔽,所以會(huì)出現(xiàn)問題。解決方法就是為待啟動(dòng)的activity指定 FLAG_ACTIVITY_NEW_TASK 標(biāo)記位宾娜,這樣啟動(dòng)的時(shí)候就會(huì)新建一個(gè)任務(wù)棧批狐,這時(shí)候,實(shí)際以 singleTask 模式啟動(dòng)的前塔。

  2. singleTop 棧頂復(fù)用模式嚣艇。這種模式下,如果該 Activity 已經(jīng)有實(shí)例位于棧頂华弓, 那么該 activity 的實(shí)例不會(huì)被重新重建食零,同時(shí)它的 onNewIntent 方法會(huì)被回調(diào),但是 onCreate该抒、onStart 等不會(huì)被調(diào)用慌洪。

  3. singleTask 棧內(nèi)復(fù)用模式。這是一種單例模式凑保,在這種模式下,只要棧存在于需要的任務(wù)棧中涌攻,多次調(diào)用都不會(huì)重新創(chuàng)建實(shí)例欧引, 系統(tǒng)也會(huì)回調(diào) OnNewIntent。
    具體說:當(dāng)一個(gè)具有 singleTask 模式的activity A請(qǐng)求啟動(dòng)后恳谎, 系統(tǒng)首先會(huì)尋找是否存在 A 想要的任務(wù)棧芝此, 如果不存在,就新建一個(gè)任務(wù)棧因痛,然后創(chuàng)建 A的實(shí)例后放入棧中婚苹。 如果A所需的任務(wù)棧存在,這時(shí)要看A是否在棧中有實(shí)例存在鸵膏, 如果有實(shí)例存在膊升,系統(tǒng)會(huì)把A調(diào)到棧頂并調(diào)用它的 onNewIntent, 如果實(shí)例不存在谭企,就創(chuàng)建A的實(shí)例廓译,并壓入棧中。

singleTask 默認(rèn)具有 clearTop 的效果债查, 會(huì)導(dǎo)致已存在的實(shí)例之上的activity全部出棧非区。

  1. singleInstance 單實(shí)例模式,這是一種加強(qiáng)的 singleTask 模式盹廷,它除了具有 singleTask 模式的所有特性以外征绸, 還加強(qiáng)了一點(diǎn),那就是具有此種模式的 activity 只能單獨(dú)地位于一個(gè)棧中。比如 Activity A是singleInstance 模式管怠, 當(dāng)A啟動(dòng)以后剥汤,系統(tǒng)會(huì)為它創(chuàng)建一個(gè)新的任務(wù)棧,然后 A 獨(dú)自存在在這個(gè)新的任務(wù)棧中排惨,由于棧內(nèi)復(fù)用的特點(diǎn)吭敢, 后續(xù)均不會(huì)創(chuàng)建新的實(shí)例,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷毀了暮芭。

幾個(gè)問題

問題1: 文中提到的某個(gè) activity所需的任務(wù)棧鹿驼, 什么是 activity 所需要的任務(wù)棧呢?

這要從一個(gè)參數(shù)說起: TaskAffinity 翻譯為任務(wù)相關(guān)性辕宏。這個(gè)參數(shù)標(biāo)識(shí)了一個(gè) activity 所需要的任務(wù)棧的名字畜晰,默認(rèn)情況下,所有 activity 所需的任務(wù)棧的名字為應(yīng)用的包名瑞筐。 當(dāng)然我們可以為每個(gè) activity 單獨(dú)指定 taskaffinity 屬性凄鼻,這個(gè)屬性要和包名不同, 否則相當(dāng)于沒指定聚假。
TaskAffinity 屬性主要和 singleTask 或者 allowTaskReparenting 屬性配對(duì)使用块蚌,其他情況下沒意義。

當(dāng)TaskAffinity和singleTask啟動(dòng)模式配對(duì)使用的時(shí)候膘格, 他是具有該模式的 Activity 的目前任務(wù)棧的名字峭范,待啟動(dòng)的 activity 會(huì)運(yùn)行在名字和 taskAffinity 名字相同的任務(wù)棧中。

問題2 什么情況下 TaskAffinity 會(huì)生效瘪贱?

只有Activity設(shè)置了 lauchMode = "singleTask" 或者 allowTaskReparenting 才起作用

Activity 的 Flags

Activity 的標(biāo)記位有很多纱控,列舉一些常用的標(biāo)記位。標(biāo)記位有多種作用菜秦√鸷Γ可以設(shè)定Activity的啟動(dòng)模式,也可以影響 activity 的運(yùn)行狀態(tài)球昨。

影響啟動(dòng)模式的:

  • FLAG_ACTIVITY_NEW_TASK 等同于xml設(shè)置 "singleTask"啟動(dòng)模式
  • FLAG_ACTIVITY_SINGLE_TOP 等同于 xml 中設(shè)置 "singleTop"啟動(dòng)模式

影響運(yùn)行狀態(tài)的:

  • FLAG_ACTIVITY_CLEAR_TOP 如果啟動(dòng)模式為 "singleTask"尔店,且該activity已存在,則清除棧中該activity之上的褪尝,只調(diào)用 onNewIntent() 闹获,不重新啟動(dòng)。
    如果啟動(dòng)模式為 “standard”河哑,那么它連同它之上的都要出棧避诽,系統(tǒng)會(huì)創(chuàng)建新的 activity并放入棧頂。
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 具有這個(gè)標(biāo)記的不會(huì)出現(xiàn)在歷史 activity 列表中璃谨,相當(dāng)于在 xml 中設(shè)置屬性 android:excludeFromRecents="true"

IntentFilter 的匹配規(guī)則

啟動(dòng) Activity 有兩種方式沙庐,顯式啟動(dòng)和隱式啟動(dòng)鲤妥。
顯式啟動(dòng)要指定被啟動(dòng)的組件信息,比較簡(jiǎn)單具體不談拱雏。
隱式啟動(dòng)則需要 intent 能夠匹配目標(biāo)組件的 IntentFilter 中所設(shè)置的過濾信息棉安。

IntentFilter 中的過濾信息有 action、category铸抑、data 三個(gè)類別贡耽,給了匹配過濾列表需要同時(shí)匹配列表中的 action, category, data信息。一個(gè)activity可以有多個(gè) IntentFilter, 一個(gè)intent只要能匹配其中一組 intentFilter 就可以啟動(dòng)對(duì)應(yīng)的 activity鹊汛。

  • action 的匹配規(guī)則

action 是一個(gè)字符串蒲赂,一個(gè)intent一般只攜帶一個(gè)action。如果攜帶多個(gè)action刁憋,則都要在 IntentFilter中包含才能正常啟動(dòng)滥嘴,但如果 Intent 中沒有指定 action 則匹配失敗。 匹配時(shí)嚴(yán)格區(qū)分大小寫至耻。 intent.setAction("..........")

  • category 的匹配規(guī)則

category 是一個(gè)字符串若皱。 如果 intent 中攜帶 category,不管攜帶幾個(gè)尘颓,都要在 IntentFilter 中找到相匹配的才能啟動(dòng)走触,若不攜帶, 系統(tǒng)會(huì)默認(rèn)設(shè)置 "android.intent.category.DEFAULT"這個(gè) category泥耀,所以在 IntentFilter 中至少要設(shè)置 <category android:name="android.intent.category.DEFAULT"/> 這一個(gè)配置項(xiàng)饺汹。否則啟動(dòng)失敗。

  • data 的匹配規(guī)則
    data 的匹配規(guī)則和 action 類似, 但是 data 要復(fù)雜的多痰催,先了解一下data 的結(jié)構(gòu) :
<data android:scheme="String"
          android:host="String"
          android:port="String"
          android:path="String"
          android:pathPattern="String"
          android:pathPrefix="String"
          android:mimeType="String"/>

data由兩部分組成: mimeType 和 URL.
mimeType 指媒體類型,如 text/plain,image/jpeg, audio/mpeg4-generic 和 video/* 等迎瞧,可以表示 文本夸溶,圖像,音頻凶硅,視頻等不同的媒體格式缝裁。
URL 包含的數(shù)據(jù)略多, 下面是 URL 的結(jié)構(gòu):

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

例子:
content://com.example.project:200/floder/subfloder/etc
http://www.baidu.com:80/search/info

每個(gè)數(shù)據(jù)的含義:
scheme: URL的模式足绅,如 http, file, content 等捷绑,如果URL中沒有指定 scheme,那么整個(gè) URL 的其他參數(shù)無效氢妈,也就意味著URL無效粹污。

Host: URL的主機(jī)名,比如 www.baidu.com, 如果 host 未指定首量,則其他參數(shù)無效壮吩,URL也無效进苍。

Port : 端口號(hào), 只有指定了 scheme 和 host 時(shí)候鸭叙, port 才有意義觉啊。

Path, PathPrefix, PathPattern: 這三個(gè)參數(shù)表述路徑信息,其中 path 表示完整的路徑信息沈贝;pathPattern

示例1:

<intent-filter>
    <data android:mimeType=" image/* " />
    ......
</intent-filter>

這種規(guī)則制定了媒體類型為照片杠人,那么intent中的mimeType為“ image/* ”才能匹配,這種情況下沒有指定URL, 但是有默認(rèn)值宋下, 默認(rèn)值是 content 和 file嗡善, 也就是說,雖然沒有指定 URL杨凑,但是 intent 中的URL部分的 scheme 必須為 content 或者 file 才能匹配滤奈。

另外,想要為 Intent 指定完整的data撩满,必須要使用 inent.setDataAndType, 不能先使用 setData 后使用 setType ,這樣會(huì)清除對(duì)方的置蜒程。

實(shí)例2:

<intent-filter>
    <data android scheme="http"  ....    android:mimeType=" video/mpeg " />
    <data android scheme="http"  ....    android:mimeType=" audio/mpeg " />
    ......
</intent-filter>

這種規(guī)則指定了兩組 data, 為了匹配實(shí)例2的規(guī)則伺帘,正確的 intent 應(yīng)該如下:

intent.setDataAndType(Url.parse("http://abc"), "video/mpeg");
或者是
intent.setDataAndType(Url.parse("http://abc"), "audio/mpeg");

最后昭躺, 如果,匹配不到合適的 activity 怎么辦伪嫁?只能奔潰么领炫?

當(dāng)我們隱式啟動(dòng)一個(gè) Activity 的時(shí)候商架,可以做一下判斷皿淋,看是否能夠匹配我們的 Intent 。方法有兩種, 都在 Context 中:

public abstract List<ResolveInfo> getPackageManager().queryIntentActivities(Intent intent做修,int flag)
或者
public abstract ResolveInfo getPackageManager().resolveActivity(Intent intent脚猾,int flag);

上述兩個(gè)方法葱峡,第一個(gè)參數(shù)沒什么好說的, 第二個(gè)參數(shù)龙助,我們要使用 PackageManager.MATCH_DEFAULT_ONLY 這個(gè)標(biāo)記砰奕, 這個(gè)標(biāo)記的含義是僅僅匹配那些在 intent-filter 中聲明了 <category android:name="android.intent.category.DEFAULT"> 這個(gè) Catrgory 的 activity, 是要返回不為null提鸟, 那么就有匹配到的activity军援, 就一定能隱式啟動(dòng)成功。因?yàn)椴缓?DEFAULT 這個(gè)category 的activity 是無法接受隱式intent的称勋。

在匹配規(guī)則中胸哥, 有一類 action 和 category 比較重要,那就是:

<action android:name="anroid.intent.action.MAIN"/>
<categoty android:name="android.intent.category.LAUCHER"/>

這兩者公共來表明一個(gè)入口 activity铣缠,并且會(huì)出現(xiàn)在Home Launcher上烘嘱。少了任何一個(gè)都不行昆禽。如果在 Intent-Filter 中還有data選項(xiàng), 則不匹配限制條件蝇庭,不能出現(xiàn)在 Home Laucher上醉鳖。 如下面這種 intent-filter:

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>

        <category android:name="android.intent.category.LAUNCHER"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
       
        <data android:scheme="urlscheme"
            android:host="auth_activity">
    </intent-filter>
</activity>

針對(duì) service 和 BroadcastReceiver ,PacketManager 同樣提供了類似的方法去獲取成功匹配的組件信息哮内。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盗棵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子北发,更是在濱河造成了極大的恐慌纹因,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件琳拨,死亡現(xiàn)場(chǎng)離奇詭異瞭恰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狱庇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門惊畏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人密任,你說我怎么就攤上這事颜启。” “怎么了浪讳?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵缰盏,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我淹遵,道長(zhǎng)口猜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任透揣,我火速辦了婚禮暮的,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘淌实。我一直安慰自己,他們只是感情好猖腕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布拆祈。 她就那樣靜靜地躺著,像睡著了一般倘感。 火紅的嫁衣襯著肌膚如雪放坏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天老玛,我揣著相機(jī)與錄音淤年,去河邊找鬼钧敞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛麸粮,可吹牛的內(nèi)容都是我干的溉苛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼弄诲,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼愚战!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起齐遵,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤寂玲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后梗摇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拓哟,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年伶授,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了断序。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谎砾,死狀恐怖逢倍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情景图,我是刑警寧澤较雕,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站挚币,受9級(jí)特大地震影響亮蒋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妆毕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一慎玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧笛粘,春花似錦趁怔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至示括,卻和暖如春铺浇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背垛膝。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工鳍侣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丁稀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓倚聚,卻偏偏與公主長(zhǎng)得像线衫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子秉沼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

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