Android进阶(二)--序列化Serializable和Parcelabel使用与区别
来源:互联网 发布:淘客cms优惠券 编辑:程序博客网 时间:2024/05/18 03:53
自己之前也做过这方面的疑惑与比较,只是一直没写成文,今天偶尔看到这样一篇不错的文章,重温习下旧知识
转载于:http://blog.csdn.net/simon_crystin/article/details/78553055
1.序列化
1.1 序列化的定义
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。简单地说,“序列化”就是将运行时的对象状态转换成二进制,然后保存到流、内存或者通过网络传输给其他端。
1.2 序列化的使用场景
我们通过Intent传递数据,官方给我们提供了许多的接口,我们可以传递整型,浮点,字符串类型等等,但是我们要传递复杂类型的就不行了,这个时候需要将复杂类型进行序列化
1.3 序列化的方式
- 实现Serializable接口(Java);
- 实现Parcelable接口(Android)。
1.4 如何选择序列化方式
1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable。
2)Serializable在序列化和反序列化频繁进行 I/O操作,非常占用内存,在序列化的时候创建许多的临时对象,容易触发垃圾回收,另外使用了反射,序列化的过程较慢。
3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelable不能很好的保证数据的持续性在外界有变化的情况下。尽管Serializable效率低点,但此时还是建议使用Serializable 。
2.Serializable 接口
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络或组件上进行传输,也可以存储到本地。
Serializable 是 Java 提供的序列化接口,它是一个空接口:
public interface Serializable {}
- 1
- 2
Serilizable序列化很多工作系统都帮我们完成了,我们只需要实现Serializable接口。
2.1 关于Serializable接口
可序列化类中,未实现 Serializable 的属性状态无法被序列化/反序列化也就是说,反序列化一个类的过程中,它的非可序列化的属性将会调用无参构造函数重新创建, 因此这个属性的无参构造函数必须可以访问,否者运行时会报错。
一个实现序列化的类,它的子类也是可序列化的;
Serializable有个唯一标识符serialVersionUID,这个serialVersionUID可以我们自己定义,也可以由系统生成,这个标识符是用来确认序列化和反序列化是不是同一个对象,是同一个对象反序列化成功,但是如果当前类有所改变,比如增加或者删除了成员变量,那么系统会重新计算当前类的hash值,赋值给serialVersionUID,发现前后不一样,序列化失败。
serialVersionUID生成方法:
1.Settings->Editor->Inspections->勾选serialVersionUID。
2.当实现Serializable接口,程序会报警告,用快捷键(我的是ALT+Enter)生成serialVersionUID.
2.2 Serilizable的实际应用
我们就以在组件Activity传递对象为例;
如何在组件中传递对象,只需要将类实现Serializable接口。
1.新建一个实体类实现Serializable接口;
** * Created by zhangcong on 2017/11/15. * @author zhangcong */public class User implements Serializable{ private static final long serialVersionUID = 8066301618436107542L; private String name; private String password; public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; }}
- 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
2.在MainActivity序列化;
public class MainActivity extends AppCompatActivity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button =findViewById(R.id.bt_click); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { User user=new User("Simon","222222"); Intent intent=new Intent(MainActivity.this, SerializableActivity.class); intent.putExtra("Simon",user); startActivity(intent); } }); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
3.在目标activity取出序列化的对象:
public class SerializableActivity extends Activity{ private TextView textView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_common); textView=findViewById(R.id.tv_text); Intent intent=getIntent(); User user= (User) intent.getSerializableExtra("Simon"); textView.setText(user.getName()+ " "+ user.getPassword()); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
3.Parcelable接口
Parcelable 是 Android 特有的序列化接口。
3.1 关于Parcelable接口
Parcelable使用时要用到一个Parcel,可以简单将其看为一个容器,序列化时将数据写入Parcel,反序列化时从中取出。
Parcelable源码:
public interface Parcelable { int CONTENTS_FILE_DESCRIPTOR = 1; int PARCELABLE_WRITE_RETURN_VALUE = 1; //描述当前 Parcelable 实例的对象类型 //比如说,如果对象中有文件描述符,这个方法就会返回上面的 CONTENTS_FILE_DESCRIPTOR //其他情况会返回一个位掩码 int describeContents(); //将对象转换成一个 Parcel 对象 //参数中 dest 表示要写入的 Parcel 对象 //flags 表示这个对象将如何写入 void writeToParcel(Parcel var1, int var2); //对象创建时提供的一个创建器 public interface ClassLoaderCreator<T> extends Parcelable.Creator<T> { //使用类加载器和之前序列化成的 Parcel 对象反序列化一个对象 T createFromParcel(Parcel var1, ClassLoader var2); } //实现类必须有一个 Creator 属性,用于反序列化,将 Parcel 对象转换为 Parcelable public interface Creator<T> { T createFromParcel(Parcel var1); T[] newArray(int var1); }}
- 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
Parcelable就是通过writeToParcel()方法进行序列化的。序列化的时候讲数据写入Parcel。想要知道Parcelable的原理,就必须弄清楚Parcel是什么?
3.2 Parcel简介:
Parcel翻译过来是打包的意思,其实就是包装了我们需要传输的数据,然后在Binder中传输,也就是用于跨进程传输数据
简单来说,Parcel提供了一套机制,可以将序列化之后的数据写入到一个共享内存中,其他进程通过Parcel可以从这块共享内存中读出字节流,并反序列化成对象,下图是这个过程的模型。
Parcel可以包含原始数据类型(用各种对应的方法写入,比如writeInt(),writeFloat()等),可以包含Parcelable对象,它还包含了一个活动的IBinder对象的引用,这个引用导致另一端接收到一个指向这个IBinder的代理IBinder。Parcelable通过Parcel实现了read和write的方法,从而实现序列化和反序列化。
3.3 Parcelable接口使用实例
1.将实体类实现Parcelable接口,我们需要重写几个方法;
/** * * @author zhangcong * @date 2017/11/16 */public class Person implements Parcelable { private String name; private int age; // 系统自动添加,给createFromParcel里面用 protected Person(Parcel in) { name=in.readString(); age=in.readInt(); } @Override public void writeToParcel(Parcel dest, int flags) { //将数据序列化到对象中 dest.writeString(name); dest.writeInt(age); } @Override public int describeContents() { //只针对一些特殊的需要描述信息的对象,需要返回1,其他情况返回0就可以 return 0; } public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel in) { // 反序列化,读取数据 return new Person(in); } //供反序列化本类数组时调用的 @Override public Person[] newArray(int size) { return new Person[size]; } }; 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; }}
- 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
2.在MainActivity开启序列化
button2=findViewById(R.id.bt_click2); button2.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { Person person=new Person("Simon",23); Intent intent2=new Intent(MainActivity.this, SerializableActivity.class); intent2.putExtra("Simon",person); startActivity(intent2); } });
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
3.在目标Activity获取对象
Intent intent=getIntent();Person person=intent.getParcelableExtra("Simon");
- 1
- 2
4.Serializable 和Parcelable的对比
android上应该尽量采用Parcelable,效率至上。
1.编码上:
Serializable代码量少,写起来方便
Parcelable代码多一些
2.效率上:
Parcelable的速度比高十倍以上。(别人测试过)
至于如何选择前面已经说了,就不赘述了。
5.Github
github
觉得有帮助的话可以star!
- Android进阶(二)--序列化Serializable和Parcelabel使用与区别
- Android进阶(二)--序列化Serializable和Parcelabel使用与区别
- Android 对象序列化 Serializable实现与Parcelabel实现的区别
- Serializable实现与Parcelabel实现的区别
- Parcelabel序列化详细使用
- Android序列化Serializable和Parcelable区别
- android 使用Intent传递对象 Serializable 或者 Parcelabel
- android (序列化) serializable 与 Parcelable
- Serializable Parcelabel
- android学习笔记3 - 序列化接口Parcelable、Serializable的使用与区别
- Android -- 序列化Parcelable与Serializable区别及用法
- Android中Serializable和Parcelable序列化的区别
- Android 进阶6:两种序列化方式 Serializable 和 Parcelable
- 序列化Serializable和Parcelable的区别
- android 使用Intent传递对象 Serializable 或者 Parcelabel 《第一行代码》
- Serializable序列化(二)
- Android Parcelable和Serializable的区别(二)
- Seralizable和Parcelabel的区别
- MySQL常用命令总结
- linux字符设备驱动-定时器按键去抖笔记
- 卷积Convolation
- Search a 2D Matrix II
- docker-compose
- Android进阶(二)--序列化Serializable和Parcelabel使用与区别
- 转载一篇c语言深度文章 《一个“蝇量级” C 语言协程库》
- Java中的内部接口
- 使用nextLine(),还没有输入,就自动输出,输出为换行
- Mybatis之添加用户(5)
- 初来乍到
- 3.4 反向输出一个三位数
- 第二次做construct2小游戏
- node 事件模板 EventEmitter 的应用