Android AIDL基礎(chǔ) -- Parcelable接口

轉(zhuǎn)載請說明出處: Android AIDL基礎(chǔ) -- Parcelable接口

什么是Parcelable接口


  • 作用:給類設(shè)計的接口,類一旦實現(xiàn)這個接口骂澄,該類的對象即可進行一個“從對象存儲為Parcel , 從Parcel讀取為對象”的一個讀寫過程惕虑。

  • 目的:實現(xiàn)序列化

  • 原因:
    序列化坟冲,為了:
    1) 永久保存對象,保存對象的字節(jié)到本地文件中
    2) 通過序列化對象在網(wǎng)絡(luò)中傳遞對象
    3) 通過序列化在進程間傳遞對象

  • 與Serializable對比:
    1)在使用Intent傳遞數(shù)據(jù)時:

    • Serializable: Bundle.putSerializable(Key, 實現(xiàn)了Serializable的對象);
    • Parcelable: Bundle.putParcelable(Key, 實現(xiàn)了Parcelable的對象);

    2)內(nèi)存使用性能上:

    • Parcelable > Serializable

    由于Serializable在序列化時會產(chǎn)生大量的臨時變量溃蔫,從而引起頻繁的GC樱衷。

    3)數(shù)據(jù)存儲在磁盤上的情況:

    • Serialzable > Parcelable

    Parcelable不能使用在要將數(shù)據(jù)存儲在磁盤上的情況,因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下酒唉。盡管Serializable效率低點,但此時還是建議使用Serializable

  • 支持的成員數(shù)據(jù)類型:
    1) 普通數(shù)據(jù)類型【如:int沸移、double等以及他們的封裝類如Integer痪伦、Float等】以及他們的數(shù)組類型【如:int[]、double[]等】注意:不支持:List[Integer]類型等List類型
    2) String/CharSequence及其數(shù)組String[]雹锣、ArrayList[String]
    3) Bundle 和 List<Bundle>
    4) Serializable 注意:不支持List<Serializable>
    5) Binder 和 List<Binder> 网沾,IBinder 和 List<IBinder>
    6) Parcelable實現(xiàn)類

    重溫:Intent/Bundle傳遞支持的數(shù)據(jù)類型有:
    * 基本數(shù)據(jù)類型和它的數(shù)組類型
    * String/CharSequence和它的數(shù)組類型
    * Serializable
    * Parcelable

實現(xiàn)Parcelable接口


  • 實現(xiàn)步驟

    1. implements Parcelable
    2. 重寫writeToParcel方法,將你的對象序列化為一個Parcel對象蕊爵,即:將類的數(shù)據(jù)寫入外部提供的Parcel中辉哥,打包需要傳遞的數(shù)據(jù)到Parcel容器保存,以便從 Parcel容器獲取數(shù)據(jù)。
    3. 重寫describeContents方法醋旦,內(nèi)容接口描述恒水,默認返回0就可以。
    4. 實例化靜態(tài)內(nèi)部對象CREATOR實現(xiàn)接口Parcelable.Creator
  • 沒有Parcelable成員的Parcelable接口實現(xiàn)示例

/** * 測試:地址

  • Created by androidjp on 16-7-22.
    */
    public class Address implements Parcelable{
    ///(可以)一般數(shù)據(jù)類型和String饲齐,如:String钉凌、int、Integer捂人、double御雕、Float等
    public String country;
    public String city;
    public String street;
    ///(可以)Bindle類型【由于Bindle本身實現(xiàn)了Parcelable】
    public Bundle bundle;
    ///(可以)Serializable類型
    public Serializable serializable;
    ///(可以)Binder類型
    public Binder binder;
    public Integer i;
    public int j;
    public List<String> stringList;
    public List<Bundle> bundleList;
    // public List<Serializable> serializableList;
    public ArrayList<IBinder> binderList;
    // public List<Integer> integerList;
    public int[] ints;

    public Address(String country, String city, String street) {
    this.country = country;
    this.city = city;
    this.street = street;
    }
    //=========================================================
    // 下面是Parcelable需要實現(xiàn)的方法
    //=========================================================
    protected Address(Parcel in) {
    country = in.readString();
    city = in.readString();
    street = in.readString();
    bundle = in.readBundle();
    serializable = in.readSerializable();
    binder = (Binder) in.readStrongBinder();
    i = in.readInt();
    j = in.readInt();
    stringList = in.createStringArrayList();
    bundleList = in.createTypedArrayList(Bundle.CREATOR);
    binderList = in.createBinderArrayList();
    ints = in.createIntArray();
    }
    /*

    • 讀取接口,目的是要從Parcel中構(gòu)造一個實現(xiàn)了Parcelable的類的實例處理滥搭。
    • 因為實現(xiàn)類在這里還是不可知的酸纲,所以需要用到模板的方式,繼承類名通過模板參數(shù)傳入瑟匆。
    • 為了能夠?qū)崿F(xiàn)模板參數(shù)的傳入闽坡,這里定義Creator嵌入接口,內(nèi)含兩個接口函數(shù)分別返回單個和多個繼承類實例。
      */
      public static final Creator<Address> CREATOR = new Creator<Address>() {
      @Override
      public Address createFromParcel(Parcel in) {
      return new Address(in);
      }
      @Override
      public Address[] newArray(int size) {
      return new Address[size];
      }
      };

    /////內(nèi)容描述接口脓诡,基本不用管
    @Override
    public int describeContents() {
    return 0;
    }
    //寫入接口函數(shù)无午,打包
    @Override
    public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(country);
    dest.writeString(city);
    dest.writeString(street);
    dest.writeBundle(bundle);
    dest.writeSerializable(serializable);
    dest.writeStrongBinder(binder);
    dest.writeInt(i);dest.writeInt(j);
    dest.writeStringList(stringList);
    dest.writeTypedList(bundleList);
    dest.writeBinderList(binderList);
    dest.writeIntArray(ints);
    }
    }

* **加上Parcelable成員的Parcelable接口實現(xiàn)示例**:

/**

  • 測試:學(xué)生
    */
    public class Student implements Parcelable{
    private int id;
    private String name;
    private Address home;////地址成員變量(已經(jīng)實現(xiàn)了Parcelable接口)
    public Student(int id, String name, Address home) {
    this.id = id;
    this.name = name;
    this.home = home;
    }
    //=========================================================
    // 下面是Parcelable需要實現(xiàn)的方法
    //=========================================================
    protected Student(Parcel in) {
    id = in.readInt();
    name = in.readString();
    home = in.readParcelable(Address.class.getClassLoader());
    }
    public static final Creator<Student> CREATOR = new Creator<Student>() {
    @Override
    public Student createFromParcel(Parcel in) {
    return new Student(in);
    }
    @Override
    public Student[] newArray(int size) {
    return new Student[size];
    }
    };
    @Override
    public int describeContents() {
    return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
    dest.writeInt(id);
    dest.writeString(name);
    dest.writeParcelable(home, flags);
    }
    }

## 擴展
---
1. 由于Parcelable對象不能向Serializable那樣將對象保存到文件中等持久化操作,那么祝谚,我的對象要怎么做宪迟?
  答: `public class Student implements Parcelable,Serializable{……`,讓類同時實現(xiàn)兩個接口交惯,即可使他能夠序列化并存儲到文件中次泽。

2. 什么是Parcel?
  答:簡單來說席爽,Parcel就是一個存放數(shù)據(jù)的容器意荤。Android中以Binder機制方式實現(xiàn)來IPC,就是使用了Parcel來進行Client和Server間的數(shù)據(jù)交互只锻,而且AIDL的數(shù)據(jù)也是通過Parcel來交互的玖像。同樣的,在Java中和C/C++中齐饮,都有Parcel的實現(xiàn)【Parcel在C/C++中捐寥,直接使用內(nèi)存來讀取數(shù)據(jù),所以此時Parcel它更加快速】
  換句話理解Parcel:我們知道祖驱,類A和類B可能想要通信握恳,那么,要進行交流捺僻,A肯定不想把自己的實例(包括成員變量乡洼、方法等)整個復(fù)制到B那邊崇裁,并且,A和B在同一個線程束昵、甚至同個進程的不同線程都好說拔稳,如果是不同進程呢?那得怎么傳妻怎,通過網(wǎng)絡(luò)之類的咯壳炎?所以,就有了Parcel這個“打包”一說逼侦,A把A的一些信息進行說明匿辩,將這些說明打包(而不同打包自己的具體東西),然后把信息傳給B榛丢,B讀了之后铲球,根據(jù)A給的提示選擇,將選擇同樣用Parcel打包傳回給A晰赞,A收到就跑稼病,跑完數(shù)據(jù)后,返回結(jié)果又同樣Parcel裝著給到B掖鱼,整個通信過程類似這樣然走。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戏挡,隨后出現(xiàn)的幾起案子芍瑞,更是在濱河造成了極大的恐慌,老刑警劉巖褐墅,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拆檬,死亡現(xiàn)場離奇詭異,居然都是意外死亡妥凳,警方通過查閱死者的電腦和手機竟贯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逝钥,“玉大人屑那,你說我怎么就攤上這事∷铱睿” “怎么了持际?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長磷箕。 經(jīng)常有香客問我,道長阵难,這世上最難降的妖魔是什么岳枷? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上空繁,老公的妹妹穿的比我還像新娘殿衰。我一直安慰自己,他們只是感情好盛泡,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布闷祥。 她就那樣靜靜地躺著,像睡著了一般傲诵。 火紅的嫁衣襯著肌膚如雪凯砍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天拴竹,我揣著相機與錄音悟衩,去河邊找鬼。 笑死栓拜,一個胖子當著我的面吹牛座泳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播幕与,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挑势,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了啦鸣?” 一聲冷哼從身側(cè)響起潮饱,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赏陵,沒想到半個月后饼齿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡蝙搔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年缕溉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吃型。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡证鸥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勤晚,到底是詐尸還是另有隱情枉层,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布赐写,位于F島的核電站鸟蜡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏挺邀。R本人自食惡果不足惜揉忘,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一跳座、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泣矛,春花似錦疲眷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至哗总,卻和暖如春几颜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背魂奥。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工菠剩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耻煤。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓具壮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哈蝇。 傳聞我的和親對象是個殘疾皇子棺妓,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容