Android 數(shù)據(jù)序列化總結(jié)

Android數(shù)據(jù)序列化總結(jié)

目錄介紹

  • 1.序列化簡單介紹
    • 1.1 序列化的概念
    • 1.2 序列化是做什么用的
    • 1.3 序列化的目的
  • 2.Serializable的使用
    • 2.1 什么是Serializable
    • 2.2 Serializable簡單實現(xiàn)
  • 3.Parcelable的使用
    • 3.1 什么是Parcelable
    • 3.2 Parcelable簡單實現(xiàn)
  • 4.Parcelable與Serializable的性能比較
    • 4.1 Serializable性能分析
    • 4.2 Parcelable性能分析
    • 4.3 性能比較總結(jié)描述
    • 4.4 性能測試方法分析
    • 4.5 兩種如何選擇
  • 5.數(shù)據(jù)的序列化方案
    • 5.1 數(shù)據(jù)序列化基礎(chǔ)
    • 5.2 SQLite
    • 5.3 SharedPreferences
    • 5.4 JSON
  • 6.其他使用
    • 6.1 Intent傳遞數(shù)據(jù)
  • 7.其他介紹
    • 7.1 參考鏈接
    • 7.2 更新日志
    • 7.3 我的博客

好消息

  • 博客筆記大匯總【16年3月到至今】马澈,包括Java基礎(chǔ)及深入知識點,Android技術(shù)博客勤婚,Python學(xué)習筆記等等馒胆,還包括平時開發(fā)中遇到的bug匯總凝果,當然也在工作之余收集了大量的面試題,長期更新維護并且修正型雳,持續(xù)完善……開源的文件是markdown格式的纠俭!同時也開源了生活博客浪慌,從12年起,積累共計47篇[近20萬字]钓简,轉(zhuǎn)載請注明出處涌庭,謝謝欧宜!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好冗茸,可以star一下匹中,謝謝豪诲!當然也歡迎提出建議屎篱,萬事起于忽微,量變引起質(zhì)變重虑!

0.備注

1.序列化的概念

  • 1.1 序列化的概念

    • 序列化是將Java對象轉(zhuǎn)化成字節(jié)序列的過程
    • 反序列化是將字節(jié)序列恢復(fù)為Java對象的過程
    • 看到網(wǎng)上還有種說法:序列化的意思籠統(tǒng)的來說就是將對象轉(zhuǎn)化成二進制揖曾,用于在文件或者網(wǎng)絡(luò)上進行傳輸亥啦;反序列化就是相反翔脱,將序列化后的二進制轉(zhuǎn)換成可以看懂的對象。
  • 1.2 序列化是做什么用的

    • 無論是在進程間通信错妖、本地數(shù)據(jù)存儲又或者是網(wǎng)絡(luò)數(shù)據(jù)傳輸都離不開序列化的支持暂氯。而針對不同場景選擇合適的序列化方案對于應(yīng)用的性能有著極大的影響亮蛔。
    • 從廣義上講,數(shù)據(jù)序列化就是將數(shù)據(jù)結(jié)構(gòu)或者是對象轉(zhuǎn)換成我們可以存儲或者傳輸?shù)臄?shù)據(jù)格式的一個過程动遭,在序列化的過程中神得,數(shù)據(jù)結(jié)構(gòu)或者對象將其狀態(tài)信息寫入到臨時或者持久性的存儲區(qū)中哩簿,而在對應(yīng)的反序列化過程中,則可以說是生成的數(shù)據(jù)被還原成數(shù)據(jù)結(jié)構(gòu)或?qū)ο蟮倪^程国裳。
    • 這樣來說全跨,數(shù)據(jù)序列化相當于是將我們原先的對象序列化概念做出了擴展浓若,在對象序列化和反序列化中蛇数,我們熟知的有兩種方法耳舅,其一是Java語言中提供的Serializable接口,其二是Android提供的Parcelable接口馏予。而在這里盔性,因為我們對這個概念做出了擴展冕香,因此也需要考慮幾種專門針對數(shù)據(jù)結(jié)構(gòu)進行序列化的方法,如現(xiàn)在那些個開放API一般返回的數(shù)據(jù)都是JSON格式的突那,又或者是我們Android原生的SQLite數(shù)據(jù)庫來實現(xiàn)數(shù)據(jù)的本地存儲愕难,從廣義上來說务漩,這些都可以算做是數(shù)據(jù)的序列化。
  • 1.3 序列化的目的

    • (1).永久的保存對象數(shù)據(jù)(將對象數(shù)據(jù)保存在文件當中,或者是磁盤中
    • (2).通過序列化操作將對象數(shù)據(jù)在網(wǎng)絡(luò)上進行傳輸(由于網(wǎng)絡(luò)傳輸是以字節(jié)流的方式對數(shù)據(jù)進行傳輸?shù)?因此序列化的目的是將對象數(shù)據(jù)轉(zhuǎn)換成字節(jié)流的形式)
    • (3).將對象數(shù)據(jù)在進程之間進行傳遞(Activity之間傳遞對象數(shù)據(jù)時,需要在當前的Activity中對對象數(shù)據(jù)進行序列化操作.在另一個Activity中需要進行反序列化操作講數(shù)據(jù)取出)
    • (4).Java平臺允許我們在內(nèi)存中創(chuàng)建可復(fù)用的Java對象翘悉,但一般情況下妖混,只有當JVM處于運行時轮洋,這些對象才可能存在弊予,即,這些對象的生命周期不會比JVM的生命周期更長(即每個對象都在JVM中)但在現(xiàn)實應(yīng)用中误褪,就可能要停止JVM運行兽间,但有要保存某些指定的對象正塌,并在將來重新讀取被保存的對象乓诽。這是Java對象序列化就能夠?qū)崿F(xiàn)該功能。(可選擇入數(shù)據(jù)庫逮壁、或文件的形式保存)
    • (5).序列化對象的時候只是針對變量進行序列化,不針對方法進行序列化.
    • (6).在Intent之間,基本的數(shù)據(jù)類型直接進行相關(guān)傳遞即可,但是一旦數(shù)據(jù)類型比較復(fù)雜的時候,就需要進行序列化操作了.

2.Serializable的使用

  • 2.1 什么是Serializable

    • 正如前面提到的窥淆,Serializable接口是Java語言的特性巍杈,是最簡單也是使用最廣泛的序列化方案之一筷畦,這邊需要注意的一點是Serializable接口是一個標識接口刺洒,無需實現(xiàn)方法逆航,Java便會對這個對象進行序列化操作因俐。
    • 在這里實現(xiàn)了Serializable接口的對象才可以序列化周偎,將Java對象轉(zhuǎn)換成字節(jié)序列蓉坎,而對應(yīng)的反序列化則是將字節(jié)序列恢復(fù)成Java對象的過程。
    • 在需要序列化的類中會用到serialVersionUID去標識這個序列化對象钳踊,即僅當序列化后的數(shù)據(jù)中的SerialVersionUID與當前類的serialVersionUID相同時才能被正常的反序列化箍土。
  • 2.2 Serializable簡單實現(xiàn)

    • 需要注意的:靜態(tài)成員變量是屬于類而不屬于對象的,所以顯然它不會參與到對象的序列化過程中弓柱。其次用transient關(guān)鍵字標記的成員變量不參與到序列化過程中侧但。最后禀横,這種序列化方式是基于磁盤或者網(wǎng)絡(luò)的。
public class Person implements Serializable{
    private static final long serialVersionUID = -7060210544600464481L;
    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;
    }
}

3.Parcelable的使用

  • 3.1 什么是Parcelable

    • Parcelable是Android SDK提供的酿箭,它是基于內(nèi)存的缭嫡,由于內(nèi)存讀寫速度高于硬盤抬闷,因此Android中的跨進程對象的傳遞一般使用Parcelable。
  • 3.2 Parcelable簡單實現(xiàn)

    • Android Parcelable code generator可以使用這個插件
      • 可以看出眷茁,實現(xiàn)一個Parcelable接口上祈,需要實現(xiàn)以下幾個方法:
      • 1.構(gòu)造函數(shù):從序列化后的對象中創(chuàng)建原始對象
      • 2.describeContents :接口內(nèi)容的描述挣磨,一般默認返回0即可
      • 3.writeToParcel:序列化的方法茁裙,將類的數(shù)據(jù)寫到parcel容器中
      • 4.靜態(tài)的parcelable.Creator接口,這個接口包含兩個方法
        • 1)createFormParcel:反序列化的方法晤锥,將Parcel還原成Java對象
        • 2)newArray:提供給外部類反序列化這個數(shù)組使用掉蔬。
public class Book implements Parcelable{
    private String bookName;
    private String author;
    private int publishDate;

    public Book(){

    }

    //寫一個構(gòu)造方法或者set方法來方便寫入數(shù)據(jù)
    public String getBookName(){
        return bookName;
    }

    public void setBookName(String bookName){
        this.bookName = bookName;
    }

    public String getAuthor(){
        return author;
    }

    public void setAuthor(String author){
        this.author = author;
    }

    public int getPublishDate(){
        return publishDate;
    }

    public void setPublishDate(int publishDate){
        this.publishDate = publishDate;
    }

    @Override
    public int describeContents(){
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags){
        //該方法將類的數(shù)據(jù)寫入外部提供的Parcel中.即打包需要傳遞的數(shù)據(jù)到Parcel容器保存,
        //以便從parcel容器獲取數(shù)據(jù)
        out.writeString(bookName);
        out.writeString(author);
        out.writeInt(publishDate);
    }

    public static final Parcelable.Creator<Book> CREATOR = new Creator<Book>(){

     @Override
        public Book[] newArray(int size){
            //從Parcel容器中讀取傳遞數(shù)據(jù)值矾瘾,封裝成Parcelable對象返回邏輯層女轿。
            return new Book[size];
        }

        @Override
        public Book createFromParcel(Parcel in){
            //從Parcel容器中讀取傳遞數(shù)據(jù)值,封裝成Parcelable對象返回邏輯層壕翩。
            return new Book(in);
        }
    };

    public Book(Parcel in){
        //如果元素數(shù)據(jù)是list類型的時候需要: lits = new ArrayList<?> in.readList(list);
        //否則會出現(xiàn)空指針異常.并且讀出和寫入的數(shù)據(jù)類型必須相同.如果不想對部分關(guān)鍵字進行序列化,可以使用transient關(guān)鍵字來修飾以及static修飾.
        bookName = in.readString();
        author = in.readString();
        publishDate = in.readInt();
    }
}

4.Parcelable與Serializable的性能比較

  • 4.1 Serializable性能分析
    • Serializable是Java中的序列化接口蛉迹,其使用起來簡單但開銷較大(因為Serializable在序列化過程中使用了反射機制,故而會產(chǎn)生大量的臨時變量放妈,從而導(dǎo)致頻繁的GC),并且在讀寫數(shù)據(jù)過程中芜抒,它是通過IO流的形式將數(shù)據(jù)寫入到硬盤或者傳輸?shù)骄W(wǎng)絡(luò)上珍策。
  • 4.2 Parcelable性能分析

    • Parcelable則是以IBinder作為信息載體,在內(nèi)存上開銷比較小宅倒,因此在內(nèi)存之間進行數(shù)據(jù)傳遞時攘宙,推薦使用Parcelable,而Parcelable對數(shù)據(jù)進行持久化或者網(wǎng)絡(luò)傳輸時操作復(fù)雜,一般這個時候推薦使用Serializable拐迁。
  • 4.3 性能比較總結(jié)描述

    • 首先Parcelable的性能要強于Serializable的原因我需要簡單的闡述一下
    • 1). 在內(nèi)存的使用中,前者在性能方面要強于后者
    • 2). 后者在序列化操作的時候會產(chǎn)生大量的臨時變量,(原因是使用了反射機制)從而導(dǎo)致GC的頻繁調(diào)用,因此在性能上會稍微遜色
    • 3). Parcelable是以Ibinder作為信息載體的.在內(nèi)存上的開銷比較小,因此在內(nèi)存之間進行數(shù)據(jù)傳遞的時候,Android推薦使用Parcelable,既然是內(nèi)存方面比價有優(yōu)勢,那么自然就要優(yōu)先選擇.
    • 4). 在讀寫數(shù)據(jù)的時候,Parcelable是在內(nèi)存中直接進行讀寫,而Serializable是通過使用IO流的形式將數(shù)據(jù)讀寫入在硬盤上.
    • 但是:雖然Parcelable的性能要強于Serializable,但是仍然有特殊的情況需要使用Serializable,而不去使用Parcelable,因為Parcelable無法將數(shù)據(jù)進行持久化,因此在將數(shù)據(jù)保存在磁盤的時候,仍然需要使用后者,因為前者無法很好的將數(shù)據(jù)進行持久化.(原因是在不同的Android版本當中,Parcelable可能會不同,因此數(shù)據(jù)的持久化方面仍然是使用Serializable)
  • 4.4 性能測試方法分析

    • 1)蹭劈、通過將一個對象放到一個bundle里面然后調(diào)用Bundle#writeToParcel(Parcel, int)方法來模擬傳遞對象給一個activity的過程,然后再把這個對象取出來线召。
    • 2)链方、在一個循環(huán)里面運行1000 次。
    • 3)灶搜、兩種方法分別運行10次來減少內(nèi)存整理祟蚀,cpu被其他應(yīng)用占用等情況的干擾工窍。
    • 4)、參與測試的對象就是上面的相關(guān)代碼
    • 5)前酿、在多種Android軟硬件環(huán)境上進行測試
  • 4.5 兩種如何選擇

    • a)在使用內(nèi)存方面患雏,Parcelable比Serializable性能高,所以推薦使用Parcelable罢维。
    • b)Serializable在序列化的時候會產(chǎn)生大量的臨時變量淹仑,從而引起頻繁的GC。
    • c)Parcelable不能使用在要將數(shù)據(jù)存儲在磁盤上的情況肺孵,因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性匀借,在外界有變化的情況下,建議使用Serializable平窘。

5.數(shù)據(jù)的序列化方案

  • 5.1 數(shù)據(jù)序列化基礎(chǔ)

    • 下面講到的是廣義上的序列化方案吓肋,不同于前面兩種狹義或者說是對象序列化方案,接下來的幾種方案針對于數(shù)據(jù)的傳輸和存儲過程中的序列化方案瑰艘。
  • 5.2 SQLite

    • SQLite主要用于存儲復(fù)雜的關(guān)系型數(shù)據(jù)是鬼,Android支持原生支持SQLite數(shù)據(jù)庫相關(guān)操作(SQLiteOpenHelper),不過由于原生API接口并不友好,所以產(chǎn)生了不少封裝了SQLite的ORM框架紫新。
  • 5.3 SharedPreferences

    • SharedPreferences是Android平臺上提供的一個輕量級存儲API均蜜,一般用于存儲常用的配置信息,其本質(zhì)是一個鍵值對存儲芒率,支持常用的數(shù)據(jù)類型如boolean囤耳、float、int偶芍、long以及String的存儲和讀取紫皇。
  • 5.4 JSON

    • JSON是一種輕量級的數(shù)據(jù)交互格式,由于其相對于XML腋寨,體積更小,在網(wǎng)絡(luò)上傳輸時更加介紹瀏覽化焕,被廣泛用于移動端萄窜。大部分APP與服務(wù)端的通信都是使用JSON格式進行交互。

6.其他使用

  • 6.1 Intent傳遞數(shù)據(jù)
    • 6.1.1 Serializable 方式
      • 相對簡單撒桨,類及其內(nèi)部的成員都實現(xiàn)Serializable接口即可查刻,不需要額外的代碼,但性能和速度上較慢凤类。
      • 查看intent.putExtra()源碼可知
public Intent putExtra(String name, Serializable value) {
    if (mExtras == null) {
        mExtras = new Bundle();
    }
    mExtras.putSerializable(name, value);
    return this;
}
    • 傳遞數(shù)據(jù)和接收數(shù)據(jù)代碼
傳遞數(shù)據(jù)
Book book=new Book();
...
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("book",book);
startActivity(intent);

接收數(shù)據(jù)
Book book= (Book) getIntent().getSerializableExtra("book");
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());

7.其他介紹

  • 7.1 參考鏈接
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2256.html
http://www.reibang.com/p/82e3090e00e0
http://www.developerphil.com/parcelable-vs-serializable/
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末佃延,一起剝皮案震驚了整個濱河市现诀,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌履肃,老刑警劉巖仔沿,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尺棋,居然都是意外死亡封锉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門膘螟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來成福,“玉大人,你說我怎么就攤上這事荆残∨” “怎么了?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵脊阴,是天一觀的道長握侧。 經(jīng)常有香客問我,道長嘿期,這世上最難降的妖魔是什么品擎? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮备徐,結(jié)果婚禮上萄传,老公的妹妹穿的比我還像新娘。我一直安慰自己蜜猾,他們只是感情好秀菱,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蹭睡,像睡著了一般衍菱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肩豁,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天脊串,我揣著相機與錄音,去河邊找鬼清钥。 笑死琼锋,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的祟昭。 我是一名探鬼主播缕坎,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼篡悟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤砖第,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后旗吁,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡停局,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年很钓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片董栽。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡码倦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锭碳,到底是詐尸還是另有隱情袁稽,我是刑警寧澤,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布擒抛,位于F島的核電站推汽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏歧沪。R本人自食惡果不足惜歹撒,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望诊胞。 院中可真熱鬧暖夭,春花似錦、人聲如沸撵孤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽邪码。三九已至裕菠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間闭专,已是汗流浹背奴潘。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留喻圃,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓粪滤,卻偏偏與公主長得像斧拍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子杖小,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355