Android 最全 Intent 傳遞資料姿勢
作為一個 Android 開發人員,我們都是用過 Intent,用它來在元件之間傳遞資料,所以說 Intent 是元件之間通訊的使者,一般情況下,我們傳遞的都是一些比較簡單的資料,並且都是基本的資料型別,寫法也比較簡單,今天我在這裡說的是如何使用 Intent 傳遞物件及集合,我們知道Intent 是不能直接傳遞沒有序列化的物件的,說到序列化,我們都知道,序列化有兩種方式,即實現 Sereriable 或者 Paracelable 介面。預設情況下,像 List、Bitmap 等預設幫我們已經實現了序列化,我們就可以直接進行傳遞,還有一些像 Map
集合,自定義的 class,預設是沒有實現序列化的介面的,我們必須要先實現序列化才可以進行傳遞。
1.傳遞序列化物件
1.1 方式一
這種方式比較簡單,我們可以先將物件使用 Gson 先序列化成 Json 字串,然後作為字串來使用 Intent,這種方式的好處是不需要實現 Sereriable 或者 Paracelable,壞處就是需要額外的使用 Gson 來序列化和解析。
程式碼示例:
ActivityA 中設定資料:
User user = new User();
user.setName("Jack");
user.setAge(18);
Intent intent=new Intent(ActivityA.this ,ActivityB.class);
intent.putExtra("user",new Gson().toJson(user));
startActivity(intent);
ActivityB 中獲取資料:
String json = getIntent().getStringExtra("user");
User user = new Gson().fromJson(json,User.class);
1.2 方式二
這種方式就是將資料封裝到 Bundle 中然後把 Bundle 物件呼叫 Intent 的 putExtra 方法然後傳遞過去,Bundle
程式碼示例:
ActivityA 中設定資料:
// 建立一個Bundle物件封裝資料
Bundle data = new Bundle();
data.putInt("age",18);
data.putString("name","Jack");
intent.putExtra("data",data);
ActivityB 中獲取資料:
Bundle data = getIntent().getBundleExtra("data");
int id = data.getInt("age");
String name = data.getString("name");
1.3 方式三
傳遞實現了 Serializable 介面的物件,這種方式也比較簡單,傳遞之前先實現 Serializable 介面,也不需要重寫方法。
程式碼示例:
ActivityA 中設定資料:
User user = new User();
user.setName("Jack");
user.setAge(18);
Intent intent=new Intent(ActivityA.this,ActivityB.class);
Bundle bundle = new Bundle();
bundle.putSerializable("user", user);
intent.putExtras(bundle);
startActivity(intent);
ActivityB 中獲取資料:
Intent intent = getIntent();
User user = (User)intent.getSerializableExtra("user");
1.4 方式四
傳遞實現了 Parcelable 介面的物件,這種方式比實現 Serializable 介面的方式稍微麻煩一點,需要重寫方法,不過我們程式設計師都是比較懶的,給大家推薦一個外掛: android-parcelable-intellij-plugin ,安裝完之後就可以使用快捷鍵自動生成實現了 Serializable 介面的物件了,是不是比較方便。
實現 Serializable 物件的 User 類示例程式碼如下:
public class User implements Parcelable {
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;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeInt(this.age);
}
public User() {
}
protected User(Parcel in) {
this.name = in.readString();
this.age = in.readInt();
}
public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>() {
@Override
public User createFromParcel(Parcel source) {
return new User(source);
}
@Override
public User[] newArray(int size) {
return new User[size];
}
};
}
傳遞資料的方法和 Serializable 類似,還是寫一下把:
程式碼示例:
ActivityA 中設定資料:
User user = new User();
user.setName("Jack");
user.setAge(18);
Intent intent=new Intent(ActivityA.this,ActivityB.class);
Bundle bundle = new Bundle();
bundle.putParcelable("user", user);
intent.putExtras(bundle);
startActivity(intent);
ActivityB 中獲取資料:
Intent intent = getIntent();
User user = (User)intent.getParcelableExtra("user");
2.傳遞集合類
2.1 傳遞 List 集合資料
如果我們要傳遞的 List 集合,我們可以把 List 強轉成 Serializable 型別,List 預設是實現了 Serializable 介面的,但是注意 List 的泛型類也必須要實現了 Serializable 介面,基本型別及包裝類就不用了。
程式碼示例:
ActivityA 中設定資料:
User user1 = new User();
user1.setName("Jack");
user1.setAge(18);
User user2 = new User();
user2.setName("Marry");
user2.setAge(20);
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras("list",(Serializable)list);
startActivity(intent);
ActivityB 中獲取資料:
Intent intent = getIntent();
List<User> list = (List<User>) getIntent().getSerializableExtra("list");
2.2 傳遞 Map 集合資料
Map介面及他的實現類預設是沒有實現序列化的介面的,我們要想傳遞 Map 就要讓 Map 實現序列化介面,我們可以自定義一個類,以HashMap為例吧,我們的類就叫 SerializableHashMap 吧,然後讓定義一個 Map 變數作為成員屬性並實現序列化介面,這樣我們的類就可以進行傳遞了,SerializableHashMap 的實現如下:
public class SerializableHashMap implements Serializable {
private HashMap<String, String> map;
public SerializableHashMap() {
}
public SerializableHashMap(HashMap<String, String> map) {
this.map = map;
}
public HashMap<String, String> getMap() {
return map;
}
public void setMap(HashMap<String, String> map) {
this.map = map;
}
}
程式碼示例:
ActivityA 中設定資料:
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Jack");
map.put("age", 18);
SerializableHashMap sMap = new SerializableHashMap();
sMap.setMap(map); // 將map資料新增到封裝的sMap中
Bundle bundle = new Bundle();
bundle.putSerializable("map", sMap);
Intent intent = new Intent(ActivityA.this,ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);
ActivityB 中獲取資料:
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
SerializableHashMap sMap = (SerializableHashMap) bundle.get("map");
HashMap<String, Object> map = sMap.getMap();
2.3 如何選擇?
另外,預設 Intent 幫我們實現了,可以支援傳遞 String 陣列等,也比較簡單,這裡就不贅述了,另外如果資料量比較大的情況下,建議使用第三方框架來進行傳遞資料,例如:EventBus 等來代替,這樣的話可以避免造成 TransactionTooLargeException。
如何選擇哪種序列化方式?弄清楚他們的區別,你也就知道使用哪個更合適了。
Serializable 和 Parcelable 介面的區別:
- 在使用記憶體的時候,Parcelable 比 Serializable 效能高,所以推薦使用 Parcelable;
- Serializable 在序列化的時候會產生大量的臨時變數,從而引起頻繁的 GC;
- Parcelable 不能使用在要將資料儲存在磁碟上的情況,因為 Parcelable 不能很好的保證資料的 持續性,在外界有變化的情況下,儘管 Serializable 效率低點,但此時還是建議使用Serializable;
好了,今天的分享就到這裡,我還是你們的大飛哥,喜歡我的文章的就點個贊,點讚的人最可愛!