原文地址:http://www.jianshu.com/p/a60b609ec7e7
一、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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
使用,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);
open.putExtra("put_ser_test", person);
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
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();
Person per = (Person)intent.getSerializableExtra("put_ser_test");
mTvDate.setText("名字:"+per.getName()+"\\n"
+"年龄:"+per.getAge());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
三、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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
系统已经帮我们做了很多事情,我们需要做的很简单,就写写我们自己需要的构造方法,写一下私有变量的 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;
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;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(color);
dest.writeInt(size);
}
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
其实说起来 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);
open.putExtra("put_ser_test", person);
/**
Bundle bundle = new Bundle();
bundle.putSerializable("bundle_ser",person);
open.putExtras(bundle);
*/
startActivity(open);
}
});
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);
mTvOpenThird.putExtra("parcel_test",tranPen);
startActivity(mTvOpenThird);
}
});
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
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);
Pen pen = (Pen)getIntent().getParcelableExtra("parcel_test");
mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate);
mTvThirdDate.setText("颜色:"+pen.getColor()+"\\n"
+"大小:"+pen.getSize());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
四、Serializable 和 Parcelable 的对比
android 上应该尽量采用 Parcelable,效率至上
编码上:
Serializable 代码量少,写起来方便
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