Intent 的用法相信你已經比較熟悉了,我們可以借助它來啟動活動、發送廣播、啟動服務等。在進行上述操作的時候,我們還可以在Intent 中添加一些附加資料,以達到傳值的效果,比如在FirstActivity 中添加如下代碼:
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("string_data", "hello");
intent.putExtra("int_data", 100);
startActivity(intent);
這裡調用了Intent 的putExtra()方法來添加要傳遞的資料,之後在SecondActivity 中就可以得到這些值了,代碼如下所示:
getIntent().getStringExtra("string_data");
getIntent().getIntExtra("int_data", 0);
但是不知道你有沒有發現,putExtra()方法中所支援的資料類型是有限的,雖然常用的一些資料類型它都會支援,但是當你想去傳遞一些自定義對象的時候就會發現無從下手。不用擔心,下面我們就學習一下使用Intent 來傳遞對象的技巧。
方式一:Serializable 方式
使用Intent 來傳遞對象通常有兩種實作方式,Serializable 和Parcelable,我們先來學習一下第一種的實作方式。
Serializable 是序列化的意思,表示将一個對象轉換成可存儲或可傳輸的狀态。序列化後的對象可以在網絡上進行傳輸,也可以存儲到本地。至于序列化的方法也很簡單,隻需要讓一個類去實作Serializable 這個接口就可以了。
比如說有一個Person 類,其中包含了name 和age 這兩個字段,想要将它序列化就可以這樣寫:
public class Person implements Serializable{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
其中get、set 方法都是用于指派和讀取字段資料的,最重要的部分是在第一行。這裡讓Person 類去實作了Serializable 接口,這樣所有的Person 對象就都是可序列化的了。
接下來在FirstActivity 中的寫法非常簡單:
Person person = new Person();
person.setName("Tom");
person.setAge(20);
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("person_data", person);
startActivity(intent);
可以看到,這裡我們建立了一個Person 的執行個體,然後就直接将它傳入到putExtra()方法中了。由于Person 類實作了Serializable 接口,是以才可以這樣寫。
接下來在SecondActivity 中擷取這個對象也很簡單,寫法如下:
Person person = (Person) getIntent().getSerializableExtra("person_data");
這裡調用了getSerializableExtra()方法來擷取通過參數傳遞過來的序列化對象,接着再将它向下轉型成Person 對象,這樣我們就成功實作了使用Intent 來傳遞對象的功能了。
方式二:Parcelable
除了Serializable 之外,使用Parcelable 也可以實作相同的效果,不過不同于将對象進行序列化,Parcelable 方式的實作原理是将一個完整的對象進行分解,而分解後的每一部分都是Intent 所支援的資料類型,這樣也就實作傳遞對象的功能了。
下面我們來看一下Parcelable 的實作方式,修改Person 中的代碼,如下所示:
public class Person implements Parcelable {
private String name;
private int age;
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
dest.writeString(name);
dest.writeInt(age);
}
public static final Parcelable.Creator<Person> CREATOR=new Parcelable.Creator<Person>() {
@Override
public Person createFromParcel(Parcel source) {
// TODO Auto-generated method stub
Person person=new Person();
person.name=source.readString();
person.age=source.readInt();
return person;
}
@Override
public Person[] newArray(int size) {
// TODO Auto-generated method stub
return new Person[size];
}
};
}
Parcelable 的實作方式要稍微複雜一些。可以看到,首先我們讓Person 類去實作了Parcelable 接口,這樣就必須重寫describeContents()和writeToParcel()這兩個方法。其中describeContents()方法直接傳回0 就可以了,而writeToParcel()方法中我們需要調用Parcel的writeXxx()方法将Person 類中的字段一一寫出。注意字元串型資料就調用writeString()方法,整型資料就調用writeInt()方法,以此類推。
除此之外,我們還必須在Person 類中提供一個名為CREATOR 的常量,這裡建立了Parcelable.Creator 接口的一個實作,并将泛型指定為Person。接着需要重寫createFromParcel()和newArray()這兩個方法,在createFromParcel()方法中我們要去讀取剛才寫出的name 和age字段,并建立一個Person 對象進行傳回,其中name 和age 都是調用Parcel 的readXxx()方法讀取到的,注意這裡讀取的順序一定要和剛才寫出的順序完全相同。而newArray()方法中的實作就簡單多了,隻需要new 出一個Person 數組,并使用方法中傳入的size 作為數組大小就可以了。
接下來在FirstActivity 中我們仍然可以使用相同的代碼來傳遞Person 對象,隻不過在SecondActivity 中擷取對象的時候需要稍加改動,如下所示:
Person person = (Person) getIntent().getParcelableExtra("person_data");
注意這裡不再是調用getSerializableExtra()方法,而是調用getParcelableExtra()方法來擷取傳遞過來的對象了,其他的地方都完全相同。這樣我們就把使用Intent 來傳遞對象的兩種實作方式都學習完了,對比一下,Serializable的方式較為簡單,但由于會把整個對象進行序列化,是以效率方面會比Parcelable 方式低一些,是以在通常情況下還是更加推薦使用Parcelable 的方式來實作Intent 傳遞對象的功能。