最近在做項目中遇到這樣一個情況:
Activity A跳轉到Activity B,Activity A設置爲launchMode:singleTask;
Activity B有一個ListView,點擊ListView的一項,返回到Activity A中,同時傳值點擊的是哪一項;(見圖:1-1,代碼:onItemClick)
然後在Activity B中Log出返回的值,但是無論如何就是獲取不到;(見代碼:getBundle,見圖:1-2)
圖 1-1
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");
}
}
圖 1-2
後來想到,Activity A使用了SingleTask的launchMode,猜想可能跟這個有關,在執行界面跳轉的時候,不會生成新的Activity A實例,所以可能不會接收到傳過來的Bundle裏面的值。於是將Activity A的launchMode改爲了Standard,果然,B傳過來的值,A可以接收到(見圖:1-3),驗證了我的猜想。
圖 1-3
但是爲什麼使用了SingleTask就不能接收到Bundle的傳值呢?
帶着疑問,我們打開了Google API的官網,找到了問題所在,罪魁禍首就是getIntent().
我們現在看看我們使用的SingleTask:
圖 1-4
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.
大致意思就是說一個Activity B如果跳轉到另一個launchMode爲SingleTask的Activity A時,如果task裏面已經有Activity A,那麼跳轉時只需要調用它裏面的onNewIntent()方法,而不是另外創建一個新的Activity
A.
那麼onNewIntent()到底是什麼?如何使用它呢?
帶着好奇,我們來查詢onNewIntent()這個方法:
圖 1-5
onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it.
這句話的大致意思是說,如果你的Task裏面已經有Activity A實例,且其他其他界面跳轉到A時不會產生新的A的實例時,onNewIntent()會被調用,通常這時候這裏面的Intent是用來重新啓動那個已經存在的A實例的。
An activity will always be paused before receiving a new intent,
so you can count on onResume()
being
called after this method.
我們的Activity A在接收到一個新的Intent的時候,會被pause掉,所以我們在調用onNewIntent()的時候,記得在之後調用onResume().(雖然讀清楚了字面意思,但是還是不知道具體怎麼操作-_-#)
這裏我們注意一下這句話:
我們之前在getBundle()方法裏(見上面代碼:getBundle)調用的是getIntent()方法,這個方法返回的是最原始啓動Actvity
A的Intent,而不是由Activity B跳轉到Activity A使用的Intent。所以我們想要拿到Activity B跳到Activity A使用的Intent,我們要使用setIntent(Intent)方法。
那麼我們如何使用setIntent(Intent)呢?
由上述表達的意思,我們隱約可以理解,setIntent(Intent)在onNewIntent(Intent)裏面,那麼setIntent方法的參數無疑使用的也是onNewIntent的參數。可是onNewIntent(Intent)方法是如何調用的呢?我們回到了上一個問題。
於是帶着思考,我們去度娘了一下,結果找到了這樣的代碼:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
表達的意思和上述onNewIntent的英文解釋一樣,當有一個Activity B跳轉到我們的singleTask Activity A時,我們在getIntent()前會先執行onNewIntent()方法,在這個方法裏,我們將接收到的新的Intent覆蓋了第一次啓動Activity A用的Intent,這樣我們在getIntent()的時候,拿到的Intent就是帶有B傳給A帶有Bundle值的Intent了。
我們將onNewIntent(Intent)方法寫在了我們的Activity A裏面,成功的得到了B傳給A的數據(效果如圖:1-3)。
PS: 第一次在CSDN裏面寫博客,有不足的地方,希望過來人指點,請多指教!