一、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()); } }

Serializable 到此完成
三、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 這兩種方式都介紹完成了。接下說一說對比
四、Serializable 和Parcelable的對比
android上應該盡量采用Parcelable,效率至上
編碼上:
Parcelable代碼量少,寫起來方便
Parcelable代碼多一些
效率上:
Parcelable的速度比高十倍以上
serializable的迷人之處在於你只需要對某個類以及它的屬性實現Serializable 接口即可。Serializable 接口是一種標識接口(marker interface),這意味着無需實現方法,Java便會對這個對象進行高效的序列化操作。
這種方法的缺點是使用了反射,序列化的過程較慢。這種機制會在序列化的時候創建許多的臨時對象,容易觸發垃圾回收。
Parcelable方式的實現原理是將一個完整的對象進行分解,而分解后的每一部分都是Intent所支持的數據類型,這樣也就實現傳遞對象的功能了
五、demo
http://pan.baidu.com/s/1dDLGWKD
參考
Android中Parcelable接口用法
http://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
Android系統中Parcelable和Serializable的區別
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0204/2410.html