天天看點

使用Intent傳遞對象的兩種方式

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 傳遞對象的功能。