此文原來是自己CSDN上的第一篇博客,因個(gè)人需要甩栈,將其復(fù)制到簡(jiǎn)書平臺(tái),另一方面也希望此文可以給安卓初學(xué)者在Activity啟動(dòng)模式中SingleTask模式下的傳值提供思路參考糕再,文風(fēng)拙劣量没,歡迎指導(dǎo)。
原文地址:
http://blog.csdn.net/wj_november/article/details/49851117
最近在做項(xiàng)目中遇到這樣一個(gè)情況:
- Activity A跳轉(zhuǎn)到Activity B突想,Activity A設(shè)置為launchMode:singleTask
- Activity B有一個(gè)ListView殴蹄,點(diǎn)擊ListView的一項(xiàng),返回到Activity A中猾担,同時(shí)傳值點(diǎn)擊的是那一項(xiàng)(見圖:1-1饶套,代碼:onItemClick)
- 然后在Activity B中Log出返回的值,但是無論如何就是獲取不到(見代碼:getBundle垒探,見圖:1-2)
onItemClick
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent intent = new Intent(BActivity.this, AActivity.class);
Bundle bundle = new Bundle();
bundle.putString(StaticValues.KEY_CAR_SERIES, seriesList.get(position));
bundle.putInt(StaticValues.KEY_CAR_SERIES_ID, position);
intent.putExtras(bundle);
startActivity(intent);
finish();
}
getBundle
private void getBundle() {
Bundle bundle = MainActivity.this.getIntent().getExtras();
if (null != bundle) {
Log.d("car", "bundle not null");
int carSeriesId = bundle.getInt(StaticValues.KEY_CAR_SERIES_ID);
String carSeries = bundle.getString(StaticValues.KEY_CAR_SERIES);
Log.d("car", carSeries + "--id=" + carSeriesId);
} else {
Log.d("car", "bundle null");
}
}
后來想到妓蛮,Activity A使用了SingleTask的launchMode,猜想可能跟這個(gè)有關(guān)圾叼,在執(zhí)行界面跳轉(zhuǎn)的時(shí)候蛤克,不會(huì)生成新的Activity A實(shí)例,所以可能不會(huì)接收到傳過來的Bundle里面的值夷蚊。于是將Activity A的launchMode改為了Standard构挤,果然,B傳過來的值惕鼓,A可以接收到(見圖:1-3)筋现,驗(yàn)證了我的猜想。
但是為什么使用了SingleTask就不能接收到Bundle的傳值呢箱歧?
帶著疑問矾飞,我們打開了Google API的官網(wǎng),找到了問題所在呀邢,罪魁禍?zhǔn)拙褪莋etIntent().我們現(xiàn)在看看我們使用的SingleTask:
The system creates the activity at the root of a new task and routes the intent to it. However, if an instance of the activity already exists, the system routes the intent to existing instance through a call to its onNewIntent() method, rather than creating a new one.
大致意思就是說一個(gè)Activity B如果跳轉(zhuǎn)到另一個(gè)launchMode為SingleTask的Activity A時(shí)洒沦,如果task里面已經(jīng)有Activity A,那么跳轉(zhuǎn)時(shí)只需要調(diào)用它里面的onNewIntent()方法价淌,而不是另外創(chuàng)建一個(gè)新的Activity A.
那么onNewIntent()到底是什么申眼?如何使用它呢?
帶著好奇蝉衣,我們來查詢onNewIntent()這個(gè)方法:
onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
這句話的大致意思是說括尸,如果你的Task里面已經(jīng)有Activity A實(shí)例,且其他其他界面跳轉(zhuǎn)到A時(shí)不會(huì)產(chǎn)生新的A的實(shí)例時(shí)病毡,onNewIntent()會(huì)被調(diào)用濒翻,通常這時(shí)候這里面的Intent是用來重新啟動(dòng)那個(gè)已經(jīng)存在的A實(shí)例的。
An activity will always be paused before receiving a new intent, so you can count on onResume() being called after this method.
我們的Activity A在接收到一個(gè)新的Intent的時(shí)候剪验,會(huì)被pause掉肴焊,所以我們?cè)谡{(diào)用onNewIntent()的時(shí)候前联,記得在之后調(diào)用onResume().(雖然讀清楚了字面意思,但是還是不知道具體怎么操作-_-#)
這里我們注意一下這句話:
Note that getIntent() still returns the original Intent. You can use setIntent(Intent) to update it to this new Intent.
我們之前在getBundle()方法里(見上面代碼:getBundle)調(diào)用的是getIntent()方法娶眷,這個(gè)方法返回的是最原始啟動(dòng)Actvity A的Intent似嗤,而不是由Activity B跳轉(zhuǎn)到Activity A使用的Intent。所以我們想要拿到Activity B跳到Activity A使用的Intent届宠,我們要使用setIntent(Intent)方法烁落。
那么我們?nèi)绾问褂胹etIntent(Intent)呢?
由上述表達(dá)的意思豌注,我們隱約可以理解伤塌,setIntent(Intent)在onNewIntent(Intent)里面,那么setIntent方法的參數(shù)無疑使用的也是onNewIntent的參數(shù)轧铁∶看希可是onNewIntent(Intent)方法是如何調(diào)用的呢?我們回到了上一個(gè)問題齿风。于是帶著思考药薯,我們?nèi)ザ饶锪艘幌拢Y(jié)果找到了這樣的代碼:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
表達(dá)的意思和上述onNewIntent的英文解釋一樣救斑,當(dāng)有一個(gè)Activity B跳轉(zhuǎn)到我們的singleTask Activity A時(shí)童本,我們?cè)趃etIntent()前會(huì)先執(zhí)行onNewIntent()方法,在這個(gè)方法里脸候,我們將接收到的新的Intent覆蓋了第一次啟動(dòng)Activity A用的Intent穷娱,這樣我們?cè)趃etIntent()的時(shí)候,拿到的Intent就是帶有B傳給A帶有Bundle值的Intent了运沦。
我們將onNewIntent(Intent)方法寫在了我們的Activity A里面泵额,成功的得到了B傳給A的數(shù)據(jù)(效果如圖:1-3)。