1.簡介
在通過Intent啟動新的Activity時,經(jīng)常需要向目標(biāo)Activity傳遞數(shù)據(jù)。從形式上來看通過Intent啟動Activity時傳遞數(shù)據(jù)有兩種方式,一是顯示的將數(shù)據(jù)放入bundle中,然后將bundle放入intent中;二是將數(shù)據(jù)直接放入Intent中。下面通過示例來展示這兩種數(shù)據(jù)的傳遞方式,并且從Android源碼分析,這兩種方式的本質(zhì)是一樣的,即都是通過Bundle來存取數(shù)據(jù)的。
2.1.通過Bundle傳遞數(shù)據(jù)
兩個Activity,從MainActivity中將數(shù)據(jù)傳遞到SecondActivity,數(shù)據(jù)類型有字符串、整形、布爾型三種。MainActivity的代碼如下:
private final static String NAME_KEY = "name";
private final static String AGE_KEY = "age";
private final static String IS_FEMALE_KEY = "isfemale";
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
Bundle data = new Bundle();
data.putString(NAME_KEY,"zhangsan");//將數(shù)據(jù)放入bundle
data.putInt(AGE_KEY,25);
data.putBoolean(IS_FEMALE_KEY,true);
intent.putExtras(data);
//在SecondActivity中,將傳遞的數(shù)據(jù)取出
Bundle data = getIntent().getExtras();//從bundle中取出數(shù)據(jù)
String name = data.getString(MainActivity.NAME_KEY);
int age = data.getInt(MainActivity.AGE_KEY);
boolean isfemale = data.getBoolean(MainActivity.IS_FEMALE_KEY);
Log.d(LOG_TAG,"name = "+name);
Log.d(LOG_TAG,"age = "+age);
Log.d(LOG_TAG,"isfemale = "+isfemale);
Bundle可以傳遞序列化對象,其方法是putSerializable(String key, Serializable value),putParcelable(String key, Parcelable value),分別可以傳遞實現(xiàn)了Serializable和Parcelb接口的對象,我比較傾向于通過這種方式傳遞數(shù)據(jù),其使用方式如下:
//存入數(shù)據(jù)
Person person = new Person();//Person是一個JavaBean,實現(xiàn)了Serializable接口
person.setName("lisi");//設(shè)置相應(yīng)的屬性值
person.setAge(27);
person.setIsfemale(true);
mIntent.putExtra(PERSON_KEY,person);
//取出數(shù)據(jù)
Bundle data = intent.getExtras();
Person person = (Person) data.getSerializable(MainActivity.PERSON_KEY);
Log.d(LOG_TAG,"name = "+person.getName());
Log.d(LOG_TAG,"age = "+person.getAge());
Log.d(LOG_TAG,"isfemale = "+person.isfemale());
2.2.省略bundle直接把數(shù)據(jù)放入Intent
//在MainActivity中存入數(shù)據(jù):
intent.putExtra(NAME_KEY,"zhangsan");
intent.putExtra(AGE_KEY,25);
intent.putExtra(IS_FEMALE_KEY,false);
//在SecondActivity中取出數(shù)據(jù):
Intent intent = getIntent();
String name = intent.getStringExtra(MainActivity.NAME_KEY);
int age = intent.getIntExtra(MainActivity.AGE_KEY,30);
boolean isfemale = intent.getBooleanExtra(MainActivity.IS_FEMALE_KEY,true);
同樣,通過Intent也可傳遞序列化對象,使用方式和Bundle的類似。
3.兩種數(shù)據(jù)傳遞方式的聯(lián)系
通過intent或者bundle傳遞數(shù)據(jù),其本質(zhì)都是通過bundle傳遞,可以通過以下方式驗證:在MainActivity中將數(shù)據(jù)直接放入intent中,在SecondActivity中先通過intent.getExtras()取出bundle,然后通過bundle的方法同樣可以取出相應(yīng)的數(shù)據(jù)。
從Android源碼來看,比如將String類型的value通過Intent的putExtra()方法放入Intent,其本質(zhì)是放入到了mExtras中,而mExtras為Bundle類型。如果mExtras不是null,則將數(shù)據(jù)放入mExtras中,否則自動新建一個并存入數(shù)據(jù)。而在取數(shù)據(jù)時,getStringExtra(String name)也是通過bundle獲取數(shù)據(jù)的,相關(guān)源碼如下:
//Intent的putExtra(String, String)方法
public Intent putExtra(String name, String value) {
if (mExtras == null) {
mExtras = new Bundle();//如果mExtras為null則直接new一個Bundle
}
mExtras.putString(name, value);//否則,將數(shù)據(jù)存入mExtras
return this;
}
//Intent的getStringExtra()方法
public String getStringExtra(String name) {
return mExtras == null ? null : mExtras.getString(name);//通過mExtras取出數(shù)據(jù)
}
4.Bundle是如何存取數(shù)據(jù)的?
Bundle是通過ArrayMap來存取數(shù)據(jù)的。
//Bundle的putString()方法
public void putString( String key, String value) {
unparcel();
mMap.put(key, value);//mMap的類型是ArrayMap
}
//Bundle的getString()方法
public String getString(String key) {
....
final Object o = mMap.get(key);
....
return (String) o;
....
}
5.總結(jié)
本文分析了通過Intent啟動Activity時傳遞數(shù)據(jù)的兩種方式,并從源碼的角度揭示了其本質(zhì)都是通過Bundle的方式進(jìn)行數(shù)據(jù)的傳遞,而Bundle是借助ArrayMap來完成數(shù)據(jù)的存取的。個人理解,難免有誤,歡迎指正交流。