大家都知道进行Android开发的时候,无法将对象的引用传给Activities或者Fragments,我们需要将这些对象放到一个Intent或者Bundle里面,然后再传递。至于怎么实现序列化,反序列化相信网上的帖子一大堆了就不一一阐述了
一. 先说说什么是序列化—— 序列化,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
二. 那么为什么要序列化?
序列化的原因基本三种情况:
1.永久性保存对象,保存对象的字节序列到本地文件中;
2.对象在网络中传递;
3.对象在IPC间传递。
三. Android中的两种序列化机制
第一种: JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设 备保存对象状 态,以及通过网络传输对象等。
第二种:在Android系统中,定位为针对内存受限的设备,因此对性能要求更高,另外系统中采用了新的IPC(进程间通信)机制,必然要求使用性能更出色的对象传输方式。在这样的环境下, Parcel被设计出来,其定位就是轻量级的高效的对象序列化和反序列化机制。
Android中序列化有以下几个特征:
1.整个读写全是在内存中进行,所以效率比JAVA序列化中使用外部存储器会高很多;
2.读写时是4字节对齐的
3.如果预分配的空间不够时,会一次多分配50%;
4.对于普通数据,使用的是mData内存地址,对于IBinder类型的数据以及FileDescriptor使用的是mObjects内存地址。 后者是通过flatten_binder()和 unflatten_binder()实现的,目的是反序列化时读出的对象就是原对象而不用重新new一个新对象。
我写了两个Activity,一个是MainActivity,里面通过intent把一个实现序列化接口的实体类User对象传递过去,
User user = new User();
user.setId(1);
user.setName("zhangsan");
Intent intent = new Intent();
intent.setClass(this, TwoActivity.class);
intent.putExtra("user", user);
startActivity(intent);
Log.d("main", user+"");
另一个TwoActivity里面,接收这个User对象:
Intent intent = this.getIntent();
User user = (User) intent.getSerializableExtra("user");
Log.d("two", user+"");
结果:打印出来的两个user指向的不是同一地址 这是为什么呢?
那么好:可以这样理解,当把一个对象从一个地方传到另一个地方,传递的不是引用,它的地址肯定会改变,世界上没有两个相同的地址。更深层次理解应该是传递前的处理:传递前根据该对象序列化,接收后反序列化再重新生成该对象,根据序列化和反序列化的规则,某些特征应该是一样的,包括值。
putSerializable,是通过对象的序列化和反序列化来实现Activity之间对象的传递的,所以这种方法得到的就是两个完全不一样的对象(Activity2中的对象obj就相当于new了一个新对象,然后将Activity1中的对象obj的值都赋给了它,所以可以说它们的内容是一样的,但是对象不一样。
再说说JAVA中的Serialize机制,译成串行化、序列化……,其作用是能将数据对象存入字节流当中,在需要时重新生成对象。主要应用是利用外部存储设备保存对象状态,以及通过网络传输对象等。
假如两个avtivity传递的是一个对象,那么当在TwoActivity里继续操作MainActivity的对象那么必将造成内存泄漏。