Activity啟動模式及Intent的Flag屬性對Intent傳值的影響

Android如何通過TextView實現(xiàn)超鏈接的跳轉(zhuǎn)CSDN博客地址:http://blog.csdn.net/zhangjinhuang/article/details/52334626

前些時候在支援公司其它部門項目開發(fā)的時候躺枕,有同事問我:通過Intent在Activity之間進行數(shù)據(jù)傳遞舀寓,傳遞的Key和獲取的Key都沒錯凭涂,為什么在目標Activity會獲取不到傳遞過來的數(shù)據(jù)摇肌?在Key沒錯的情況下獲取不到數(shù)據(jù),那么無疑是Activity的啟動模式及在跳轉(zhuǎn)時給Intent設(shè)置的Flag屬性引起的删壮,于是乎有了今天這篇博客贸诚。

原因一:Activity的啟動模式

那么Activity以哪種啟動模式進行跳轉(zhuǎn)時,會導(dǎo)致目標Activity獲取不到傳遞過來的數(shù)據(jù)呢翩瓜?在上一篇Activity啟動模式詳解博客中講到Activity以不同的啟動模式進行啟動會根據(jù)啟動模式來創(chuàng)建相應(yīng)的實例,也就是說携龟,如果目標Activity的實例已經(jīng)存在并且符合要求兔跌,則不會再創(chuàng)建相應(yīng)的實例,因此在Activity的4種啟動模式中峡蟋,以singleTop(有可能)坟桅、singleTask、singleInstance模式啟動的目標Activity蕊蝗,當置于后臺被再次啟動時都會導(dǎo)致目標Activity獲取不到傳遞過來的數(shù)據(jù)(這里指的獲取不到是指在不借助其它操作時)仅乓。

這里以singleTop模式來講解,當在StandardActivity中點擊SingleTopActivity按鈕時蓬戚,會將輸入的內(nèi)容或者默認的內(nèi)容通過Intent傳遞給目標SingleTopActivity然后獲取并顯示出來夸楣,主要代碼代碼如下所示:

public void skip2SingleTopActivity(View?view){

Intent?intent?=newIntent(StandardActivity.this,SingleTopActivity.class);

content?=?et_content.getText().toString().trim();

if(TextUtils.isEmpty(content)){

content?="這是從StandardActivity傳遞過來的內(nèi)容";

}

intent.putExtra(SingleTopActivity.SINGLE_TOP,content);

startActivity(intent);

}

目標SingleTopActivity獲取并顯示數(shù)據(jù)的代碼如下所示:

private void getBundleData()?{

Log.i(TAG,"getBundleData");

Intent?intent?=?getIntent();

if(intent?!=null)?{

result?=?intent.getStringExtra(SINGLE_TOP);

tv_content.setText("結(jié)果為:"+?result);

}

}

其中g(shù)etBundleData方法是在onCreate方法中調(diào)用的,點擊后的結(jié)果如下所示:

可以看到目標SingleTopActivity可以成功獲取傳遞過來的數(shù)據(jù)子漩,現(xiàn)在重點來了豫喧,如果此時在SingleTopActivity中的EditText中輸入內(nèi)容或者直接點擊SingleTopActivity按鈕讓它繼續(xù)跳轉(zhuǎn)到自己會出現(xiàn)什么情況呢?

跳轉(zhuǎn)的主要代碼如下所示:

publicvoidskip2SingleTopActivity(View?view)?{

Intent?intent?=newIntent(SingleTopActivity.this,?SingleTopActivity.class);

String?content?=?et_content.getText().toString().trim();

if(TextUtils.isEmpty(content))?{

content?="這是從SingleTopActivity傳遞過來的數(shù)據(jù)";

}

intent.putExtra(SINGLE_TOP,?content);

startActivity(intent);

}

此時SingleTopActivity中顯示的數(shù)據(jù)依然是從StandardActivity中傳過來的數(shù)據(jù):

原因二:Intent設(shè)置的Flag屬性

Intent對象大致包含Component痛单、Action嘿棘、Category、Data旭绒、Type鸟妙、Extra和Flag這7種屬性,其中Intent的Flag屬性用于為該Intent添加一些額外的控制旗標挥吵,可以通過Intent的addFlags方法為Intent添加控制旗標重父。

其中常見的跟Activity跳轉(zhuǎn)有關(guān)的Flag旗桿有如下幾個:

1、FLAG_ACTIVITY_BROUGHT_TO_FRONT:經(jīng)測試發(fā)現(xiàn)以該旗標啟動的目標Activity跟以旗標FLAG_ACTIVITY_NEW_TASK啟動的目標Activity一樣都會創(chuàng)建新的Activity實例忽匈。

2房午、FLAG_ACTIVITY_CLEAR_TOP:見名知意:清除當前Activity之上的所有實例,該Flag相當于Activity啟動模式中的singleTask丹允,例如郭厌,一個Activity棧中包含有A、B雕蔽、C折柠、D,4個Activity實例批狐,當在Activity D中以該旗標啟動Activity B時扇售,此時Activity棧中只包含A、B兩個Activity實例。

在ActivityD中以FLAG_ACTIVITY_CLEAR_TOP標志啟動之前:

在ActivityD中以FLAG_ACTIVITY_CLEAR_TOP標志啟動之后:

3承冰、FLAG_ACTIVITY_NEW_TASK:默認啟動旗標华弓,該旗標控制創(chuàng)建一個新的Activity實例,該Flag相當于Activity啟動模式中的standard困乒。

4寂屏、FLAG_ACTIVITY_SINGLE_TOP:從名字中不難看出該Flag相當于Activity加載模式中的singleTop模式,即原來Activity棧中有A顶燕、B凑保、C、D這4個Activity實例涌攻,當在Activity D中再次啟動Activity D時欧引,Activity棧中依然還是A、B恳谎、C芝此、D這4個Activity實例。

5因痛、FLAG_ACTIVITY_NO_HISTORY:如名字沒有歷史Activity一樣婚苹,以該旗標啟動的Activity不會保留在Activity棧中,如:Activity棧中有A鸵膏、B兩個Activity實例膊升,當在Activity B中以該旗標啟動Activity C,在Activity C中再啟動Activity D谭企,此時Activity棧中只有A廓译、B、D三個Activity實例债查,即Activity C不會保留在Activity棧中非区。

當然也可以通過在Activity D中以FLAG_ACTIVITY_CLEAR_TOP旗標的方式啟動Activity C,如果Activity C還保留在Activity棧中的話盹廷,那么此時棧中的肯定只有A征绸、B、C這三個Activity的實例俄占,但是實踐證明Activity棧中有A管怠、B、D缸榄、C這四個實例渤弛,也就進一步說明在Activity B中以FLAG_ACTIVITY_NO_HISTORY旗標啟動Activity C,再在Activity C中啟動Activity D后碰凶,Activity C不會在保留在Activity棧中暮芭,所以才會出現(xiàn)當在Activity D中以FLAG_ACTIVITY_CLEAR_TOP旗標的方式啟動Activity C時會創(chuàng)建新的Activity C實例,棧中情況如下所示:

6欲低、FLAG_ACTIVITY_REORDER_TO_FRONT:即如果棧中已有該Activity則直接將該Activity帶到前臺辕宏。如:Activity棧中有A、B砾莱、C瑞筐、D四個Activity,如果在Activity D使用該旗標啟動Activity C腊瑟,那么啟動后Activity棧中的情形為:A-B-D-C聚假。

啟動前Activity棧中的情況:

啟動后Activity棧中的情況:

從原因一:Activity的啟動模式中可以發(fā)現(xiàn),如果Activity棧中已經(jīng)存在目標Activity的實例的話闰非,當從后臺再次返回到Activity的棧頂時都有可能導(dǎo)致目標Activity獲取不到傳遞過來的數(shù)據(jù)膘格,同樣的,原因二:Intent設(shè)置的Flag屬性如果也會讓目標Activity的實例保留在Activity棧中且滿足條件的話當再次啟動時也會導(dǎo)致目標Activity獲取不到傳遞過來的數(shù)據(jù)财松,這里本來也將會通過以Activity的singleTop啟動模式相對應(yīng)的FLAG_ACTIVITY_SINGLE_TOP旗標來講解的瘪贱,不過由于篇幅原因,所以打消了這種想法辆毡,如果真有需要的話菜秦,可以去下載源碼查看。

解決方案:

知道原因之后舶掖,那么該如何解決這個問題呢球昨?其實谷歌早就考慮到了這種問題,于是在Androidapi中的Activity類中給我們提供了一個叫onNewIntent的方法來解決這個問題:

當一個Activity的啟動模式是singleTop或者使用FLAG_ACTIVITY_SINGLE_TOP這個標記啟動的時候眨攘,并且Activity的棧頂就是待啟動的目標Activity的時候主慰,會調(diào)用目標Activity的這個方法,如果需要在后續(xù)的目標Activity的生命周期中可以獲取最新的數(shù)據(jù)期犬,可以在該方法中通過setIntent方法更新數(shù)據(jù)河哑。(ps:不完全是按照翻譯)

知道了解決辦法以后,在目標SingleTopActivity重寫onNewIntent方法并在該方法中通過setIntent方法來更新數(shù)據(jù)以確保在目標SingleTopActivity后續(xù)的生命周期中可以獲取最新的數(shù)據(jù)龟虎,主要代碼如下所示:

@Override

protected void onNewIntent(Intent?intent)?{

super.onNewIntent(intent);

if(intent?!=null)?{

result?=?intent.getStringExtra(SINGLE_TOP);

Log.e(TAG,"onNewIntent?result=="+?result);

setIntent(intent);

}

}

@Override

protected void onResume()?{

super.onResume();

Log.e(TAG,"onResume");

Intent?intent?=?getIntent();

if(intent?!=null)?{

result?=?intent.getStringExtra(SINGLE_TOP);

tv_content.setText("結(jié)果為:"+?result);

}

}

此時璃谨,輸入內(nèi)容并點擊SingleTopActivity按鈕可以發(fā)現(xiàn)已經(jīng)可以獲取最新的數(shù)據(jù)了,結(jié)果如下所示:

Log日志如下所示:

至此鲤妥,Activity啟動模式及Intent的Flag屬性對Intent傳值的影響就介紹完了佳吞。

另外,為了方便開發(fā)棉安,很多公司都會封裝一些常用的工具類底扳,如:為了減少Activity實例的的創(chuàng)建,會對Activity的跳轉(zhuǎn)進行一系列的封裝的IntentUtils工具類中往往會給Intent添加addFlags方法以減少實例的創(chuàng)建贡耽,因此小伙伴們在使用自己公司封裝好的工具類時需要時刻留意衷模。

后記:

其實鹊汛,現(xiàn)在想想,或許對Intent進行封裝時添加Flag旗標也許不是一個明智的選擇阱冶,就拿FLAG_ACTIVITY_SINGLE_TOP來說刁憋,這個旗標也只是在當目標Activity已對處于Activity棧頂?shù)臅r候才不會再次去創(chuàng)建目標Activity的實例,所以說如果添加Flag是為了減少實例的創(chuàng)建的話也不現(xiàn)實木蹬,并且在開發(fā)中很多終端頁都是借助WebView加載h5來實現(xiàn)的至耻,如果在終端頁中點擊某個鏈接會繼續(xù)在當前Activity中打開,這個時候就會遇到一個很尷尬的問題镊叁,雖然內(nèi)容是變了尘颓,但是看不到Activity的任何切換并且此時點擊返回鍵的時候是會直接退出當前Activity,而不是回到上一個h5顯示的頁面(也許你會說晦譬,可以監(jiān)聽返回鍵然后在相應(yīng)的事件中對WebView進行判斷疤苹,這樣就不會直接退出了,如果你要這樣想的話敛腌,我也是沒轍的)痰催,當然,如果你們公司的產(chǎn)品覺得這樣蠻好的迎瞧,那又是另一回事了夸溶,畢竟這一切都是我個人的看法,況且:一切用戶至上凶硅!

源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缝裁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子足绅,更是在濱河造成了極大的恐慌捷绑,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氢妈,死亡現(xiàn)場離奇詭異粹污,居然都是意外死亡,警方通過查閱死者的電腦和手機首量,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門壮吩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人加缘,你說我怎么就攤上這事鸭叙。” “怎么了拣宏?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵沈贝,是天一觀的道長。 經(jīng)常有香客問我勋乾,道長宋下,這世上最難降的妖魔是什么嗡善? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮学歧,結(jié)果婚禮上滤奈,老公的妹妹穿的比我還像新娘。我一直安慰自己撩满,他們只是感情好喜最,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布药磺。 她就那樣靜靜地躺著厉碟,像睡著了一般锈颗。 火紅的嫁衣襯著肌膚如雪届谈。 梳的紋絲不亂的頭發(fā)上企巢,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天哮奇,我揣著相機與錄音西壮,去河邊找鬼偶垮。 笑死张咳,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的似舵。 我是一名探鬼主播脚猾,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼砚哗!你這毒婦竟也來了龙助?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤蛛芥,失蹤者是張志新(化名)和其女友劉穎提鸟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仅淑,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡称勋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涯竟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赡鲜。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖庐船,靈堂內(nèi)的尸體忽然破棺而出蝗蛙,到底是詐尸還是另有隱情,我是刑警寧澤醉鳖,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布捡硅,位于F島的核電站,受9級特大地震影響盗棵,放射性物質(zhì)發(fā)生泄漏壮韭。R本人自食惡果不足惜北发,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喷屋。 院中可真熱鬧琳拨,春花似錦、人聲如沸屯曹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恶耽。三九已至密任,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間偷俭,已是汗流浹背浪讳。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留涌萤,地道東北人淹遵。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像负溪,于是被迫代替她去往敵國和親透揣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

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