Android數據序列化總結html
目錄介紹
0.備註
1.序列化的概念
-
1.1 序列化的概念框架
- 序列化是將Java對象轉化成字節序列的過程
- 反序列化是將字節序列恢復爲Java對象的過程
- 看到網上還有種說法:序列化的意思籠統的來講就是將對象轉化成二進制,用於在文件或者網絡上進行傳輸;反序列化就是相反,將序列化後的二進制轉換成能夠看懂的對象。
-
1.2 序列化是作什麼用的ide
- 不管是在進程間通訊、本地數據存儲又或者是網絡數據傳輸都離不開序列化的支持。而針對不一樣場景選擇合適的序列化方案對於應用的性能有着極大的影響。
- 從廣義上講,數據序列化就是將數據結構或者是對象轉換成咱們能夠存儲或者傳輸的數據格式的一個過程,在序列化的過程當中,數據結構或者對象將其狀態信息寫入到臨時或者持久性的存儲區中,而在對應的反序列化過程當中,則能夠說是生成的數據被還原成數據結構或對象的過程。
- 這樣來講,數據序列化至關因而將咱們原先的對象序列化概念作出了擴展,在對象序列化和反序列化中,咱們熟知的有兩種方法,其一是Java語言中提供的Serializable接口,其二是Android提供的Parcelable接口。而在這裏,由於咱們對這個概念作出了擴展,所以也須要考慮幾種專門針對數據結構進行序列化的方法,如如今那些個開放API通常返回的數據都是JSON格式的,又或者是咱們Android原生的SQLite數據庫來實現數據的本地存儲,從廣義上來講,這些均可以算作是數據的序列化。
-
1.3 序列化的目的
- (1).永久的保存對象數據(將對象數據保存在文件當中,或者是磁盤中
- (2).經過序列化操做將對象數據在網絡上進行傳輸(因爲網絡傳輸是以字節流的方式對數據進行傳輸的.所以序列化的目的是將對象數據轉換成字節流的形式)
- (3).將對象數據在進程之間進行傳遞(Activity之間傳遞對象數據時,須要在當前的Activity中對對象數據進行序列化操做.在另外一個Activity中須要進行反序列化操做講數據取出)
- (4).Java平臺容許咱們在內存中建立可複用的Java對象,但通常狀況下,只有當JVM處於運行時,這些對象纔可能存在,即,這些對象的生命週期不會比JVM的生命週期更長(即每一個對象都在JVM中)但在現實應用中,就可能要中止JVM運行,但有要保存某些指定的對象,並在未來從新讀取被保存的對象。這是Java對象序列化就可以實現該功能。(可選擇入數據庫、或文件的形式保存)
- (5).序列化對象的時候只是針對變量進行序列化,不針對方法進行序列化.
- (6).在Intent之間,基本的數據類型直接進行相關傳遞便可,可是一旦數據類型比較複雜的時候,就須要進行序列化操做了.
2.Serializable的使用
-
2.1 什麼是Serializable
- 正如前面提到的,Serializable接口是Java語言的特性,是最簡單也是使用最普遍的序列化方案之一,這邊須要注意的一點是Serializable接口是一個標識接口,無需實現方法,Java便會對這個對象進行序列化操做。
- 在這裏實現了Serializable接口的對象才能夠序列化,將Java對象轉換成字節序列,而對應的反序列化則是將字節序列恢復成Java對象的過程。
- 在須要序列化的類中會用到serialVersionUID去標識這個序列化對象,即僅當序列化後的數據中的SerialVersionUID與當前類的serialVersionUID相同時才能被正常的反序列化。
-
2.2 Serializable簡單實現
- 須要注意的:靜態成員變量是屬於類而不屬於對象的,因此顯然它不會參與到對象的序列化過程當中。其次用transient關鍵字標記的成員變量不參與到序列化過程當中。最後,這種序列化方式是基於磁盤或者網絡的。
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提供的,它是基於內存的,因爲內存讀寫速度高於硬盤,所以Android中的跨進程對象的傳遞通常使用Parcelable。
-
3.2 Parcelable簡單實現
public class Book implements Parcelable{
private String bookName;
private String author;
private int publishDate;
public Book(){
}
//寫一個構造方法或者set方法來方便寫入數據
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){
//該方法將類的數據寫入外部提供的Parcel中.即打包須要傳遞的數據到Parcel容器保存,
//以便從parcel容器獲取數據
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容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層。
return new Book[size];
}
@Override
public Book createFromParcel(Parcel in){
//從Parcel容器中讀取傳遞數據值,封裝成Parcelable對象返回邏輯層。
return new Book(in);
}
};
public Book(Parcel in){
//若是元素數據是list類型的時候須要: lits = new ArrayList<?> in.readList(list);
//不然會出現空指針異常.而且讀出和寫入的數據類型必須相同.若是不想對部分關鍵字進行序列化,可使用transient關鍵字來修飾以及static修飾.
bookName = in.readString();
author = in.readString();
publishDate = in.readInt();
}
}
4.Parcelable與Serializable的性能比較
-
4.1 Serializable性能分析
- Serializable是Java中的序列化接口,其使用起來簡單但開銷較大(由於Serializable在序列化過程當中使用了反射機制,故而會產生大量的臨時變量,從而致使頻繁的GC),而且在讀寫數據過程當中,它是經過IO流的形式將數據寫入到硬盤或者傳輸到網絡上。
-
4.2 Parcelable性能分析
- Parcelable則是以IBinder做爲信息載體,在內存上開銷比較小,所以在內存之間進行數據傳遞時,推薦使用Parcelable,而Parcelable對數據進行持久化或者網絡傳輸時操做複雜,通常這個時候推薦使用Serializable。
-
4.3 性能比較總結描述
- 首先Parcelable的性能要強於Serializable的緣由我須要簡單的闡述一下
- 1). 在內存的使用中,前者在性能方面要強於後者
- 2). 後者在序列化操做的時候會產生大量的臨時變量,(緣由是使用了反射機制)從而致使GC的頻繁調用,所以在性能上會稍微遜色
- 3). Parcelable是以Ibinder做爲信息載體的.在內存上的開銷比較小,所以在內存之間進行數據傳遞的時候,Android推薦使用Parcelable,既然是內存方面比價有優點,那麼天然就要優先選擇.
- 4). 在讀寫數據的時候,Parcelable是在內存中直接進行讀寫,而Serializable是經過使用IO流的形式將數據讀寫入在硬盤上.
- 可是:雖然Parcelable的性能要強於Serializable,可是仍然有特殊的狀況須要使用Serializable,而不去使用Parcelable,由於Parcelable沒法將數據進行持久化,所以在將數據保存在磁盤的時候,仍然須要使用後者,由於前者沒法很好的將數據進行持久化.(緣由是在不一樣的Android版本當中,Parcelable可能會不一樣,所以數據的持久化方面仍然是使用Serializable)
-
4.4 性能測試方法分析
- 1)、經過將一個對象放到一個bundle裏面而後調用Bundle#writeToParcel(Parcel, int)方法來模擬傳遞對象給一個activity的過程,而後再把這個對象取出來。
- 2)、在一個循環裏面運行1000 次。
- 3)、兩種方法分別運行10次來減小內存整理,cpu被其餘應用佔用等狀況的干擾。
- 4)、參與測試的對象就是上面的相關代碼
- 5)、在多種Android軟硬件環境上進行測試
-
4.5 兩種如何選擇
- a)在使用內存方面,Parcelable比Serializable性能高,因此推薦使用Parcelable。
- b)Serializable在序列化的時候會產生大量的臨時變量,從而引發頻繁的GC。
- c)Parcelable不能使用在要將數據存儲在磁盤上的狀況,由於Parcelable不能很好的保證數據的持續性,在外界有變化的狀況下,建議使用Serializable。
5.數據的序列化方案
-
5.1 數據序列化基礎
- 下面講到的是廣義上的序列化方案,不一樣於前面兩種狹義或者說是對象序列化方案,接下來的幾種方案針對於數據的傳輸和存儲過程當中的序列化方案。
-
5.2 SQLite
- SQLite主要用於存儲複雜的關係型數據,Android支持原生支持SQLite數據庫相關操做(SQLiteOpenHelper),不過因爲原生API接口並不友好,因此產生了很多封裝了SQLite的ORM框架。
-
5.3 SharedPreferences
- SharedPreferences是Android平臺上提供的一個輕量級存儲API,通常用於存儲經常使用的配置信息,其本質是一個鍵值對存儲,支持經常使用的數據類型如boolean、float、int、long以及String的存儲和讀取。
-
5.4 JSON
- JSON是一種輕量級的數據交互格式,因爲其相對於XML,體積更小,在網絡上傳輸時更加介紹瀏覽,被普遍用於移動端。大部分APP與服務端的通訊都是使用JSON格式進行交互。
6.其餘使用
-
6.1 Intent傳遞數據
-
6.1.1 Serializable 方式
- 相對簡單,類及其內部的成員都實現Serializable接口便可,不須要額外的代碼,但性能和速度上較慢。
- 查看intent.putExtra()源碼可知
public Intent putExtra(String name, Serializable value) {
if (mExtras == null) {
mExtras = new Bundle();
}
mExtras.putSerializable(name, value);
return this;
}
傳遞數據
Book book=new Book();
...
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("book",book);
startActivity(intent);
接收數據
Book book= (Book) getIntent().getSerializableExtra("book");
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());
7.其餘介紹
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2256.html
https://www.jianshu.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 個人博客