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.備注
- 建議結(jié)合代碼缺厉,看博客更加高效隧土,項目地址:https://github.com/yangchong211/
- 博客大匯總曹傀,持續(xù)更新目錄說明,記錄所有開源項目和博客
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ù)組使用掉蔬。
- Android Parcelable code generator可以使用這個插件
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()源碼可知
- 6.1.1 Serializable 方式
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());
6.1.2 Parcelable 方式
速度較Serializable快10倍以上穗泵,但實現(xiàn)起來較復(fù)雜,關(guān)于Parcelable的使用請參考這篇文章:http://www.reibang.com/p/82e3090e00e0
6.1.3 將對象轉(zhuǎn)為Json字符串傳遞谜疤,或者將Json轉(zhuǎn)化成對象傳遞
可以直接參考這篇文章:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2256.html
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/
-
7.2 更新日志
- v1.0.0 2017年3月28日
- v1.1.0 2018年1月29日
-
7.3 我的博客