1. 程式人生 > >Android通過Intent傳遞資料

Android通過Intent傳遞資料

日常開發中,我們經常遇到通過 Intent 來傳遞資料,預設情況,我們可以看到支援的資料型別:

intent

基本型別:boolean、byte、char 、short、double、float、int、long
字串型別:String、String[]、CharSequence、CharSequence[]
序列化型別:Serializable、Parcelable
其他型別:八種基本型別的陣列、IntegerArray、StringArray、CharSequenceArray、ParcelableArray
基本型別我們比較好理解,接下來我們做簡要分析。

當然,如果你使用Bundle也是一樣的。

對於基本型別我們可以不做任何處理即可在Activity或者Service中傳遞。那麼對於自定義型別,我們怎麼做呢?

何謂序列化

當我們需要對JVM中的java物件進行轉儲時,就需要將其轉化成二進位制序列,然後才能儲存到外部。這個序列中儲存了java物件的型別,資料,資料型別等。當需要的時候,再對儲存的二進位制序列進行反序列化,即可將其還原。常見的場景比如:儲存JVM中物件,通過Socket傳遞java物件,RMI等等。

String型別

為什麼把這個放在第一位呢?
原因很簡單:簡單

基本型別不用說,直接傳遞即可,對於我們的自定義型別,如果你跟我一樣,不太喜歡(熟悉 T-T)Serializable和Parcelable,那用String型別最簡單了。其實這個說法還有個前提,就是我們的專案中需要整合json工具(不過至少有gson)。使用方法如下:首先通過json工具將我們的Object轉換成json字串,然後在接收處在通過json工具還原為Object。

從效率來看,會比下面兩種情況低。但是對初學者來說,會比下面兩種用起來簡單。目前還沒有遇到出錯的問題(可能時因為我傳遞的資料比較小比較簡單吧)。

Serializable

Java中經常會遇到 Serializable,比如這樣:

public class Person implements Serializable {
    public String name;
    public int age;
    public boolean login;
    public float score;
}

有些地方需要進行序列化時,IDE會提示我們實現一個介面:Serializable

,然後我們乖乖地加上這個介面即可(有時候IDE還會自動生成一個靜態常量:private static final long serialVersionUID = 23333333333333333333L;)。如果你沒有去追究為什麼,那麼事情就此結束。通過Intent傳遞資料時,也是如此。好了,我們進入下一部分~~

哈哈,哪能這麼簡單。你可能會問,為什麼加個這個介面即可?Serializable是一種 標記介面,當我們實現這個介面之後,系統會自動通過反射機制將我們物件的成員進行序列化。這裡會涉及一些其他資訊,比如:serialVersionUID、靜態常量的序列化等等,更多資訊請參考這裡

Parcelable

Parcelable是android特有的處理序列化的方法。先看簡單的使用:

  • 建立一個類:

    public class User implements Parcelable {
        public String userName;
        public int age;
        public boolean login;
        public float score;
    }
  • 使用AndroidStudio的程式碼生成功能生成如下 模版 程式碼:

    public class User implements Parcelable {
    public String userName;
    public int age;
    public boolean login;
    public float score;
    
    protected User(Parcel in) {
        userName = in.readString();
        age = in.readInt();
        login = in.readByte() != 0;
        score = in.readFloat();
    }
    
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(userName);
        dest.writeInt(age);
        dest.writeByte((byte) (login ? 1 : 0));
        dest.writeFloat(score);
    }
    
    @Override
    public int describeContents() {
        return 0;
    }
    
    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }
    
        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
    }

    對比上面的兩段程式碼,我們可以發現:

  • 構造方法中接收一個 Parcel 物件,通過這個物件對成員變數賦值

  • 實現了 Parcelable 介面的方法

    • writeToParcel 方法中將我們的成員變數寫入 Parcel
    • describeContents 中返回一個數字 0

      Describe the kinds of special objects contained in this Parcelable instance’s marshaled representation. For example, if the object will include a file descriptor in the output of writeToParcel(Parcel, int), the return value of this method must include the CONTENTS_FILE_DESCRIPTOR bit.

  • 建立了一個 public static final 常量 CREATOR

這樣我們就可以通過Intent傳遞物件了。

在android的很多文章中都可以看到,Intent中傳遞資料,強烈推薦使用 Parcelable 他的效率會比 Serializable更高(比如後者沒有使用反射等等)。當然沒有完美的事情,Parcelable 並不能完全取代Serializable,比如將JVM物件儲存到磁碟等等。但是對於Android開發中的通過Intent傳遞資料來說,已經足夠。

參考: