Android中的Serializable和Parcelable
来源:互联网 发布:泰牛程序员学费多少 编辑:程序博客网 时间:2024/06/02 03:07
本篇有部分内容:1、Android studio 中设置自动生成serialVersionUID。2、serialVersionUID作用 3、Parcelable
上篇文章我们知道了如何开启一个线程,也知道了多进程会导致的问题。不过不用担心,系统提供了很多跨进程通信的方法,虽说还是不能直接共享内存,但是可以通过跨进程通信还是可以实现数据交互。
方式很多:通过Intent传递数据,共享文件和SharedPreference(并发有问题),基于Binder的AIDL和Socket等。
Serializable和Parcelable统称为序列化,他们作用是将对象转换成可存储和传输的状态。例如:保存到本地文件,网络传输时,甚至两个Activity传输数据时。
先说Serializable
Android studio serialVersionUID生成
Serializable是Java提供的一个序列化接口,是一个空接口,为对象提供标准的序列化和反序列化操作。使用Serializable实现序列化很简单,只要实现这个接口,并在其中添加一个标识:
private static final long serialVersionUID = -765267859799146771L;
这个标识可以自动生成,也可以直接自己成一个值,如,1L什么的。
有人说,我的studio为毛不能自动生成 serialVersionUID 啊,别急,此处默认不生成也没有提示,需要我们设置一下。
步骤:
1. AS->Settings->Inspections->Java->Serializations issues->Serializable class without ‘serialVersionUID’ 勾选中,apply即可。
2. 然后,选中implements Serializable的类名,Alt+Enter,根据提示操作。
序列化操作
下面的例子中会使用到getDir()等,关于几种Android中获取路径方法,可参考Android存储使用参考
User类
public class User implements Serializable{ private int age; private String name; public User(int age, String name) { this.age = age; this.name = name; } 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,两个button,一个textview。
/** * 序列化 */public void save(View view) { File externalFilesDir = getExternalFilesDir(""); File file = new File(externalFilesDir, "test.txt"); if (!file.exists()) { try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file)); objectOutputStream.writeObject(new User(18, "Lily")); objectOutputStream.close(); Log.d(TAG, "save: 序列化完毕!"); } catch (IOException e) { e.printStackTrace(); }}/** * 反序列化 */public void restore(View view) { File file = new File(getExternalFilesDir(""), "test.txt"); try { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file)); User user = (User) objectInputStream.readObject(); textView.setText(user.getName() + "\t" + user.getAge()); objectInputStream.close(); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); }}
操作及结果
serialVersionUID作用
有人说了,我擦,你上面serialVersionUID什么都没写。
别慌,这时候没什么错。我们稍微改动一下上面的User,添加一个isMale。这时我们再去点击反序列化(本初不点击“序列化”,本地已经存储)
public class User implements Serializable{ private int age; private String name; private boolean isMale; ******}
会报一个错误
java.io.InvalidClassException: com.breezehan.serializable.User; local class incompatible: stream classdesc serialVersionUID = -7507481965945576883, local class serialVersionUID = -9068471045426611656
就是,两者的serialVersionUID 的不对照,没法儿反序列化。
这里的serialVersionUID ,是程序根据当前类的结构(变量、方法等),计算出来的一个hash值。
想看serialVersionUID 的作用,我们添加serialVersionUID = 1L,或者自动生成,进行序列化,然后添加isMale,进行反序列化,你会发现,这次会成功的。
serialVersionUID 工作机制(摘自Android开发艺术探索)
序列化的时候系统会把当前类的serialVersionUID 写入序列化的文件中(也可能是其他中介),当反序列化的时候系统会去检测文件中的serialVersionUID ,看是否和当前类的serialVersionUID 一致,如果一致就说明序列化的类的版本和当前类的版本是相同的,这个时候可以成功反序列化;否则就说明当前类和序列化的类相比发生了某些变换,比如成员变量的数量、类型可能发生了改变,这个时候是无法正常反序列的。
我们添加了serialVersionUID ,也只能说最大程度上避免反序列化失败。比如,我们可能删除或增加了一些成员变量,这个时候可以成功;但是当类结构发生了非常规性的改变,比如修改了类名,变量类型,这个时候仍然会失败。
Parcelable实现
public class People implements Parcelable { private int age; private String name; private boolean isMale; private Book book; protected People(Parcel in) { age = in.readInt(); name = in.readString(); isMale = in.readByte() != 0; book = in.readParcelable(Book.class.getClassLoader()); } public static final Creator<People> CREATOR = new Creator<People>() { @Override public People createFromParcel(Parcel in) { return new People(in); } @Override public People[] newArray(int size) { return new People[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(age); dest.writeString(name); dest.writeByte((byte) (isMale ? 1 : 0)); dest.writeParcelable(book, flags); }}
看起来挺复杂,但是其实studio都会自动帮我们生成。
Android开发艺术探索中注释
然后我们就可以在intent和binder中使用了。其中writeToParcel是序列化,反序列化是CREATOR,最终通过Parcel 的一系列read完成。
Parcelable与Serializable区别
Serializable是java中的方法,使用简单但是开销大,有大量I/O操作。Parcelable是Android特有的序列化方法,性能较高。
在内存中使用时,建议Parcelable;存储或网络传输时建议Serializable(Parcelable也能实现,较复杂)。
- Android中的Serializable和Parcelable
- Android中的Serializable和Parcelable
- Android中的Serializable和Parcelable序列化
- Android中的Serializable和Parcelable的qubie
- Android中的序列化Serializable和Parcelable
- android: Serializable 和 Parcelable
- 【Android】Serializable和Parcelable
- Android中的Parcelable接口和Serializable用法和区别
- [android] Serializable 和 Parcelable 区别
- android---- Serializable 和 Parcelable 区别
- android---- Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- [android] Serializable 和 Parcelable 区别
- 在做性能测试之前需要知道什么
- C多线程编程以及线程函数
- Oracle RAC
- QT程序在发布的时候应注意的地方
- php的Mysql数据库连接类
- Android中的Serializable和Parcelable
- 原生js拖拽
- SSTF 调度算法 磁盘
- 移动端固定输入框在底部会被键盘遮挡的解决方法
- QT中获取选中的radioButton的两种方法
- 如何快速转载CSDN上的博客
- GOTURN 算法
- js值类型和引用类型
- Flow Tables