1. 程式人生 > >Android 最全 Intent 傳遞資料姿勢

Android 最全 Intent 傳遞資料姿勢

點選上面藍色字型關注“IT大飛說”

置頂公眾號(ID:ITBigFly)第一時間收到推送

這裡寫圖片描述

作為一個 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 物件呼叫 IntentputExtra 方法然後傳遞過去,Bundle

類預設也是已經實現了 Parcelable 介面的,所以可以傳遞 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

如何選擇哪種序列化方式?弄清楚他們的區別,你也就知道使用哪個更合適了。

SerializableParcelable 介面的區別:

  • 在使用記憶體的時候,ParcelableSerializable 效能高,所以推薦使用 Parcelable
  • Serializable 在序列化的時候會產生大量的臨時變數,從而引起頻繁的 GC
  • Parcelable 不能使用在要將資料儲存在磁碟上的情況,因為 Parcelable 不能很好的保證資料的 持續性,在外界有變化的情況下,儘管 Serializable 效率低點,但此時還是建議使用Serializable

好了,今天的分享就到這裡,我還是你們的大飛哥,喜歡我的文章的就點個贊,點讚的人最可愛!

這裡寫圖片描述

掃一掃,開啟我們的的緣分


可能不是最好的公眾號,但肯定是最良心的公眾號!