序列化Serializable和Parcelable的理解和區別
一、android為什麼要序列化?什麼是序列化,怎麼進行序列化
why
為什麼要了解序列化?—— 進行Android開發的時候,無法將物件的引用傳給Activities或者Fragments,我們需要將這些物件放到一個Intent或者Bundle裡面,然後再傳遞。
what
什麼是序列化 —— 序列化,表示將一個物件轉換成可儲存或可傳輸的狀態。序列化後的物件可以在網路上進行傳輸,也可以儲存到本地。
how
怎麼通過序列化傳輸物件?
Android中Intent如果要傳遞類物件,可以通過兩種方式實現。
- 方式一:Serializable,要傳遞的類實現Serializable介面傳遞物件,
- 方式二:Parcelable,要傳遞的類實現Parcelable介面傳遞物件。
Serializable(Java自帶):
Serializable是序列化的意思,表示將一個物件轉換成可儲存或可傳輸的狀態。序列化後的物件可以在網路上進行傳輸,也可以儲存到本地。
Parcelable(android 專用):
除了Serializable之外,使用Parcelable也可以實現相同的效果,
不過不同於將物件進行序列化,Parcelable方式的實現原理是將一個完整的物件進行分解,
而分解後的每一部分都是Intent所支援的資料型別,這樣也就實現傳遞物件的功能了。
實現Parcelable的作用
1)永久性儲存物件,儲存物件的位元組序列到本地檔案中;
2)通過序列化物件在網路中傳遞物件;
3)通過序列化在程式間傳遞物件。
選擇序列化方法的原則
1)在使用記憶體的時候,Parcelable比Serializable效能高,所以推薦使用Parcelable。
2)Serializable在序列化的時候會產生大量的臨時變數,從而引起頻繁的GC。
3)Parcelable不能使用在要將資料儲存在磁碟上的情況,因為Parcelable不能很好的保證資料的持續性在外界有變化的情況下。儘管Serializable效率低點,但此時還是建議使用Serializable 。
應用場景
需要在多個部件(Activity或Service)之間通過Intent傳遞一些資料,簡單型別(如:數字、字串)的可以直接放入Intent。複雜型別必須實現Parcelable介面。
二、利用java自帶的Serializable 進行序列化的例子
弄一個實體類 Person,利用Java自帶的Serializable進行序列化
package com.amqr.serializabletest.entity;
import java.io.Serializable;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:16
* Describe: Describe Text
*/
public class Person implements Serializable{
private static final long serialVersionUID = 7382351359868556980L;
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
使用,MainActivity和SecondActivity結合使用
MainActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Person;
/**
* 進行Android開發的時候,我們都知道不能將物件的引用傳給Activities或者Fragments,
* 我們需要將這些物件放到一個Intent或者Bundle裡面,然後再傳遞。
*
*
* Android中Intent如果要傳遞類物件,可以通過兩種方式實現。
* 方式一:Serializable,要傳遞的類實現Serializable介面傳遞物件,
* 方式二:Parcelable,要傳遞的類實現Parcelable介面傳遞物件。
*
* Serializable(Java自帶):
* Serializable是序列化的意思,表示將一個物件轉換成可儲存或可傳輸的狀態。序列化後的物件可以在網路上進行傳輸,也可以儲存到本地。
*
* Parcelable(android 專用):
* 除了Serializable之外,使用Parcelable也可以實現相同的效果,
* 不過不同於將物件進行序列化,Parcelable方式的實現原理是將一個完整的物件進行分解,
* 而分解後的每一部分都是Intent所支援的資料型別,這樣也就實現傳遞物件的功能了。
要求被傳遞的物件必須實現上述2種介面中的一種才能通過Intent直接傳遞。
*/
public class MainActivity extends Activity {
private TextView mTvOpenNew;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.mTvOpenNew).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent open = new Intent(MainActivity.this,SecondActivity.class);
Person person = new Person();
person.setName("一去二三裡");
person.setAge(18);
// 傳輸方式一,intent直接呼叫putExtra
// public Intent putExtra(String name, Serializable value)
open.putExtra("put_ser_test", person);
// 傳輸方式二,intent利用putExtras(注意s)傳入bundle
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
}
}
SecondActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Person;
/**
* User: LJM
* Date&Time: 2016-02-22 & 11:56
* Describe: Describe Text
*/
public class SecondActivity extends Activity{
private TextView mTvDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
mTvDate = (TextView) findViewById(R.id.mTvDate);
Intent intent = getIntent();
// 關鍵方法:getSerializableExtra ,我們的類是實現了Serializable介面的,所以寫這個方法獲得物件
// public class Person implements Serializable
Person per = (Person)intent.getSerializableExtra("put_ser_test");
//Person per = (Person)intent.getSerializableExtra("bundle_ser");
mTvDate.setText("名字:"+per.getName()+"\\n"
+"年齡:"+per.getAge());
}
}
三、android專用的Parcelable的序列化的例子
我們寫一個實體類,實現Parcelable介面,馬上就被要求
1、複寫describeContents方法和writeToParcel方法
2、例項化靜態內部物件CREATOR,實現介面Parcelable.Creator 。
也就是,隨便一個類實現了Parcelable介面就一開始就會變成這樣子
Parcelable方式的實現原理是將一個完整的物件進行分解,而分解後的每一部分都是Intent所支援的資料型別,這樣也就實現傳遞物件的功能了。
public class Pen implements Parcelable{
private String color;
private int size;
protected Pen(Parcel in) {
color = in.readString();
size = in.readInt();
}
public static final Creator<Pen> CREATOR = new Creator<Pen>() {
@Override
public Pen createFromParcel(Parcel in) {
return new Pen(in);
}
@Override
public Pen[] newArray(int size) {
return new Pen[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color);
dest.writeInt(size);
}
}
系統已經幫我們做了很多事情,我們需要做的很簡單,就寫寫我們自己需要的構造方法,寫一下私有變數的get和set
大概變成這樣子:
package com.amqr.serializabletest.entity;
import android.os.Parcel;
import android.os.Parcelable;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:52
* Describe: Describe Text
*/
public class Pen implements Parcelable{
private String color;
private int size;
// 系統自動新增,給createFromParcel裡面用
protected Pen(Parcel in) {
color = in.readString();
size = in.readInt();
}
public static final Creator<Pen> CREATOR = new Creator<Pen>() {
/**
*
* @param in
* @return
* createFromParcel()方法中我們要去讀取剛才寫出的name和age欄位,
* 並建立一個Person物件進行返回,其中color和size都是呼叫Parcel的readXxx()方法讀取到的,
* 注意這裡讀取的順序一定要和剛才寫出的順序完全相同。
* 讀取的工作我們利用一個建構函式幫我們完成了
*/
@Override
public Pen createFromParcel(Parcel in) {
return new Pen(in); // 在建構函式裡面完成了 讀取 的工作
}
//供反序列化本類陣列時呼叫的
@Override
public Pen[] newArray(int size) {
return new Pen[size];
}
};
@Override
public int describeContents() {
return 0; // 內容介面描述,預設返回0即可。
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color); // 寫出 color
dest.writeInt(size); // 寫出 size
}
// ======分割線,寫寫get和set
//個人自己新增
public Pen() {
}
//個人自己新增
public Pen(String color, int size) {
this.color = color;
this.size = size;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
}
其實說起來Parcelable寫起來也不是很麻煩,在as裡面,我們的一個實體類寫好私有變數之後,讓這個類繼承自Parcelable,接下的步驟是:
1、複寫兩個方法,分別是describeContents和writeToParcel
2、例項化靜態內部物件CREATOR,實現介面Parcelable.Creator 。 以上這兩步系統都已經幫我們自動做好了
3、自己寫寫我們所需要的構造方法,變數的get和set
實現自Parcelable實體Bean已經寫好了,接下來我們結合MainActivity和ThirdActivity來使用以下:
MainActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import com.amqr.serializabletest.entity.Pen;
import com.amqr.serializabletest.entity.Person;
/**
* 進行Android開發的時候,我們都知道不能將物件的引用傳給Activities或者Fragments,
* 我們需要將這些物件放到一個Intent或者Bundle裡面,然後再傳遞。
*
*
* Android中Intent如果要傳遞類物件,可以通過兩種方式實現。
* 方式一:Serializable,要傳遞的類實現Serializable介面傳遞物件,
* 方式二:Parcelable,要傳遞的類實現Parcelable介面傳遞物件。
*
* Serializable(Java自帶):
* Serializable是序列化的意思,表示將一個物件轉換成可儲存或可傳輸的狀態。序列化後的物件可以在網路上進行傳輸,也可以儲存到本地。
*
* Parcelable(android 專用):
* 除了Serializable之外,使用Parcelable也可以實現相同的效果,
* 不過不同於將物件進行序列化,Parcelable方式的實現原理是將一個完整的物件進行分解,
* 而分解後的每一部分都是Intent所支援的資料型別,這樣也就實現傳遞物件的功能了。
要求被傳遞的物件必須實現上述2種介面中的一種才能通過Intent直接傳遞。
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.mTvOpenNew).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent open = new Intent(MainActivity.this, SecondActivity.class);
Person person = new Person();
person.setName("一去二三裡");
person.setAge(18);
// 傳輸方式一,intent直接呼叫putExtra
// public Intent putExtra(String name, Serializable value)
open.putExtra("put_ser_test", person);
// 傳輸方式二,intent利用putExtras(注意s)傳入bundle
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
// 採用Parcelable的方式
findViewById(R.id.mTvOpenThird).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mTvOpenThird = new Intent(MainActivity.this,ThirdActivity.class);
Pen tranPen = new Pen();
tranPen.setColor("big red");
tranPen.setSize(98);
// public Intent putExtra(String name, Parcelable value)
mTvOpenThird.putExtra("parcel_test",tranPen);
startActivity(mTvOpenThird);
}
});
}
}
ThirdActivity
package com.amqr.serializabletest;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import com.amqr.serializabletest.entity.Pen;
/**
* User: LJM
* Date&Time: 2016-02-22 & 14:47
* Describe: Describe Text
*/
public class ThirdActivity extends Activity{
private TextView mTvThirdDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_third);
mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate);
// Intent intent = getIntent();
// Pen pen = (Pen)intent.getParcelableExtra("parcel_test");
Pen pen = (Pen)getIntent().getParcelableExtra("parcel_test");
mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate);
mTvThirdDate.setText("顏色:"+pen.getColor()+"\\n"
+"大小:"+pen.getSize());
}
}
四、Serializable 和Parcelable的對比
android上應該儘量採用Parcelable,效率至上
編碼上:
Serializable程式碼量少,寫起來方便
Parcelable程式碼多一些
效率上:
Parcelable的速度比Serializable 高十倍以上
serializable的迷人之處在於你只需要對某個類以及它的屬性實現Serializable 介面即可。Serializable 介面是一種標識介面(marker interface),這意味著無需實現方法,Java便會對這個物件進行高效的序列化操作。
這種方法的缺點是使用了反射,序列化的過程較慢。這種機制會在序列化的時候建立許多的臨時物件,容易觸發垃圾回收。
Parcelable方式的實現原理是將一個完整的物件進行分解,而分解後的每一部分都是Intent所支援的資料型別,這樣也就實現傳遞物件的功能了
相關文章
- Serializable和Parcelable的區別
- Parcelable和Serializable知識總結
- Android重修課 — Serializable&ParcelableAndroid
- Android重修課 -- Serializable&ParcelableAndroid
- Java序列化和hessian序列化的區別Java
- java的序列化SerializableJava
- 教你理解let和var的區別
- 深入理解equals和==的區別
- Serializable java序列化Java
- 個人理解Vue和React區別VueReact
- 什麼是序列化?物件和類的區別?物件
- Python序列化模組pickle和json使用和區別PythonJSON
- 【轉】理解 CI 和 CD 之間的區別
- ../和./和/的區別
- Java入門學習- 理解List和HashMap和HashTable的用法和區別JavaHashMap
- Java中HashMap和TreeMap的區別深入理解JavaHashMap
- 對SSO單點登入和OAuth2.0的區別和理解OAuth
- 和 的區別
- as 和 with的區別
- ||和??的區別
- /*和/**的區別
- 什麼是Java Serializable(序列化)Java
- Java序列化(Serializable)與反序列化詳解Java
- LinkedList和ArrayList的區別、Vector和ArrayList的區別
- http和https的區別/get和post的區別HTTP
- 徹底理解斜槓和反斜槓的區別
- Python 原始碼理解: '+=' 和 'xx = xx + xx' 的區別Python原始碼
- ./ 和sh 的區別
- JQuery this和$(this)的區別jQuery
- jquery $(this) 和this的區別jQuery
- T和?的區別
- ++a和a++的區別
- makefile =和:=的區別
- 和區別
- 我已經理解了併發和並行的區別並行
- Python面試之理解__new__和__init__的區別Python面試
- HTML之position:absolute relative static fixed的區別和理解HTML
- 如何理解UDP 和 TCP? 區別? 應用場景?UDPTCP