浅谈Android中的序列化
来源:互联网 发布:淘宝手机尺寸是多少 编辑:程序博客网 时间:2024/05/16 15:18
转载请附原文链接:http://blog.csdn.net/a774057695/article/details/50440617
首先,的确是想写点东西安慰自己还在坚持写东西。
写这个,只是念头中有这个东西,前段时间面试几个刚接受过培训的新人的时候,问了一个看有没有灵性的问题,因为现在用xml的太少了,顺口问了一下json的解析库会不会使用,比如fastjson,(当然不会深入去问的,毕竟刚出来),然后就有目的的问了一个看有没有灵性,擅不擅长思考的问题咯:app内跨activity传值、传对象怎么做,倒是都在答parcelable接口的东西,追问有没有其他省力的方法时,没有人说用json的。好吧,这一篇就大概回顾一些相关的内容。谈parcelable接口之前,我们先看看Java 中的序列化Serializable:
Serialization(序列化)是一种将对象以一连串的字节描述的过程;
deserialization(反序列化)是一种将一连串的字节重建为一个对象的过程。
也就是说,这里只会牵涉到: 对象、一连串字节。
2、那么,哪些情景需要进行序列化 ?
a)将一个对象以“一连串的字节”形式保存时,例如写到一个文件、数据库。
b)使用套接字在网络上传送对象时,而且我们都会想到流
c)通过序列化在进程间传输对象时 ——这个和我们问题是相关的
3、序列化怎么做?
java中,将需要序列化的类实现Serializable接口即可,需要注意:Serializable接口中没有定义任何方法。
4、序列化和反序列化demo
序列化一个对象,首先要创建某些OutputStream(例如FileOutputStream、ByteArrayOutputStream等),然后将这些OutputStream封装在一个ObjectOutputStream中。
然后调用writeObject()方法,就可以将对象序列化,并将其发送给OutputStream
注意:我们之前提到序列化只和 对象,字节相关,所以不能使用Reader、Writer等和字符相关的东西。
顺理成章的,反序列需要将一个InputStream(例如FileInputstream、ByteArrayInputStream等)封装在ObjectInputStream内,然后调用readObject(),就可以获得想要的对象。
以下是一个demo,对Test类实现序列化package test;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;/** * @ClassName: Serialization * @Description: TODO * @date 2015年12月31日 上午11:56:46 * * @author leobert.lan * @version 1.0 */public class Serialization {public static void main(String[] args) {try {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("my.out"));Test mTest = new Test();mTest.str1 = "111";mTest.str2 = "222";oos.writeObject(mTest);oos.flush();oos.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}deserialization();}/** * @Title: deserialization * @Description: 反序列化 * @author: leobert.lan */public static void deserialization() {ObjectInputStream oin = null;try {oin = new ObjectInputStream(new FileInputStream("my.out"));} catch (FileNotFoundException e1) {e1.printStackTrace();} catch (IOException e1) {e1.printStackTrace();}Test test = null;try {test = (Test) oin.readObject();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}System.out.println("str1 :" + test.str1);System.out.println("str2 :" + test.str2);}}class Test implements Serializable {/** * serialVersionUID:TODO(用一句话描述这个变量表示什么). */private static final long serialVersionUID = 1L;String str1;String str2;}
5、序列化ID,serialVersionUID
刚才的代码中出现了一个静态常量:serialVersionUID
它的作用,我也说不出一朵花来,简单来说,Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。
序列化 ID 在 Eclipse 下提供了两种生成策略,一个是固定的 1L,一个是随机生成一个不重复的 long 类型数据(有人说实际上是使用 JDK 工具生成,还有人进一步说是根据当前类结构哈希出来的)。
6.我们可能比较关心序列化前和序列化后的对象是一致的吗?
进一步说,关心的是:是同一个对象,还是两个内容一致的对象
当然是两个对象,只是内容一致,内存地址是不一致的,也就是说,你操作其中一个,另一个是不受影响的。
引用一句话吧,“通过序列化操作,我们可以实现对任何可Serializable对象的“深度复制(deep copy)”——这意味着我们复制的是整个对象网,而不仅仅是基本对象及其引用。对于同一流的对象,他们的地址是相同,说明他们是同一个对象,但是与其他流的对象地址却不相同。也就说,只要将对象序列化到单一流中,就可以恢复出与我们写出时一样的对象网,而且只要在同一流中,对象都是同一个。”
需要注意的是:
1类静态常量是类层面的,不是对象层面的,所以serialVersionUID是不会被序列化的(请不要形而上的理解);
2当一个父类实现序列化,子类已然实现了序列化。因为序列化是通过实现Serializable接口;3当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;
4transient修饰的变量不能被序列化
上面的内容说的是java中的序列化,我们看看Android中的序列化
Android当然可以像java一样使用Serializable接口实现序列化,但是并不推荐,还有就是实现Parcelable接口,这是Android特有的,效率比实现Serializable接口高,可结合Intent传递数据,也可以用于进程间通信(IPC))。实现Parcelable接口相对复杂一些。
Android中Intent传递对象有两种方法:
1:Bundle.putSerializable(Key,Object);需要实现Serializable接口
2::Bundle.putParcelable(Key,Object);需要实现Parcelable接口
1.了解一下parcelable接口内容
public interface Parcelable { /** * Flag for use with {@link #writeToParcel}: the object being written * is a return value, that is the result of a function such as * "<code>Parcelable someFunction()</code>", * "<code>void someFunction(out Parcelable)</code>", or * "<code>void someFunction(inout Parcelable)</code>". Some implementations * may want to release resources at this point. */ public static final int PARCELABLE_WRITE_RETURN_VALUE = 0x0001; /** * Bit masks for use with {@link #describeContents}: each bit represents a * kind of object considered to have potential special significance when * marshalled. */ public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001; /** * Describe the kinds of special objects contained in this Parcelable's * marshalled representation. * * @return a bitmask indicating the set of special object types marshalled * by the Parcelable. */ public int describeContents(); /** * Flatten this object in to a Parcel. * * @param dest The Parcel in which the object should be written. * @param flags Additional flags about how the object should be written. * May be 0 or {@link #PARCELABLE_WRITE_RETURN_VALUE}. */ public void writeToParcel(Parcel dest, int flags); /** * Interface that must be implemented and provided as a public CREATOR * field that generates instances of your Parcelable class from a Parcel. */ public interface Creator<T> { /** * Create a new instance of the Parcelable class, instantiating it * from the given Parcel whose data had previously been written by * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}. * * @param source The Parcel to read the object's data from. * @return Returns a new instance of the Parcelable class. */ public T createFromParcel(Parcel source); /** * Create a new array of the Parcelable class. * * @param size Size of the array. * @return Returns an array of the Parcelable class, with every entry * initialized to null. */ public T[] newArray(int size); } /** * Specialization of {@link Creator} that allows you to receive the * ClassLoader the object is being created in. */ public interface ClassLoaderCreator<T> extends Creator<T> { /** * Create a new instance of the Parcelable class, instantiating it * from the given Parcel whose data had previously been written by * {@link Parcelable#writeToParcel Parcelable.writeToParcel()} and * using the given ClassLoader. * * @param source The Parcel to read the object's data from. * @param loader The ClassLoader that this object is being created in. * @return Returns a new instance of the Parcelable class. */ public T createFromParcel(Parcel source, ClassLoader loader); }}直接copy了android中的源码
那么实现了接口之后要做哪些工作呢?
1.重写describeContents(),默认返回0就OK了。
2.重写writeToParcel(),该方法将对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
3.实例化静态内部对象CREATOR实现接口Parcelable.Creator
给一个例子:
package com.example.androidtest;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.Parcel;import android.os.Parcelable;public class MainActivity extends Activity {<span style="white-space:pre"></span><span style="white-space:pre"></span>@Override<span style="white-space:pre"></span>protected void onCreate(Bundle savedInstanceState) {<span style="white-space:pre"></span>super.onCreate(savedInstanceState);<span style="white-space:pre"></span>setContentView(R.layout.activity_main);<span style="white-space:pre"></span>Test t = new Test();<span style="white-space:pre"></span>t.setmIntData(1);<span style="white-space:pre"></span>t.setmStringData("str");<span style="white-space:pre"></span>Intent i = new Intent(MainActivity.this,SecondActivity.class);<span style="white-space:pre"></span>Bundle b = new Bundle();<span style="white-space:pre"></span>b.putParcelable("key", t);<span style="white-space:pre"></span>i.putExtras(b);<span style="white-space:pre"></span>startActivity(i);<span style="white-space:pre"></span>}<span style="white-space:pre"></span><span style="white-space:pre"></span><span style="white-space:pre"></span>}class Test implements Parcelable {<span style="white-space:pre"></span>private int mIntData;<span style="white-space:pre"></span><span style="white-space:pre"></span>private String mStringData;<span style="white-space:pre"></span><span style="white-space:pre"></span>public int getmIntData() {<span style="white-space:pre"></span>return mIntData;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public void setmIntData(int mIntData) {<span style="white-space:pre"></span>this.mIntData = mIntData;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public String getmStringData() {<span style="white-space:pre"></span>return mStringData;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public void setmStringData(String mStringData) {<span style="white-space:pre"></span>this.mStringData = mStringData;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public int describeContents() {<span style="white-space:pre"></span>return 0;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public void writeToParcel(Parcel out, int flags) {<span style="white-space:pre"></span>out.writeInt(mIntData);<span style="white-space:pre"></span>out.writeString(mStringData);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public static final Parcelable.Creator<Test> CREATOR = new Parcelable.Creator<Test>() {<span style="white-space:pre"></span>public Test createFromParcel(Parcel in) {<span style="white-space:pre"></span>return new Test(in);<span style="white-space:pre"></span>}<span style="white-space:pre"></span>public Test[] newArray(int size) {<span style="white-space:pre"></span>return new Test[size];<span style="white-space:pre"></span>}<span style="white-space:pre"></span>};<span style="white-space:pre"></span>private Test(Parcel in) {<span style="white-space:pre"></span>mIntData = in.readInt();<span style="white-space:pre"></span>mStringData = in.readString();<span style="white-space:pre"></span>}<span style="white-space:pre"></span><span style="white-space:pre"></span>public Test() {}}package com.example.androidtest;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;public class SecondActivity extends Activity {<span style="white-space:pre"></span>private final String tag = "SecondActivity";<span style="white-space:pre"></span>@Override<span style="white-space:pre"></span>protected void onCreate(Bundle savedInstanceState) {<span style="white-space:pre"></span>super.onCreate(savedInstanceState);<span style="white-space:pre"></span>setContentView(R.layout.activity_second);<span style="white-space:pre"></span><span style="white-space:pre"></span>Intent i = getIntent();<span style="white-space:pre"></span>Test t = i.getParcelableExtra("key");<span style="white-space:pre"></span>Log.d(tag, "int data:"+t.getmIntData()+"\r\nString data:"+t.getmStringData());<span style="white-space:pre"></span>}}
总之,用起来的时候比较烦,要写很多东西,而且非常重要的一点就是,
public void writeToParcel(Parcel out, int flags) {<span></span>out.writeInt(mIntData);<span></span>out.writeString(mStringData);<span></span>}<span></span>private Test(Parcel in) {<span></span>mIntData = in.readInt();<span></span>mStringData = in.readString();<span></span>}
这两个方法写和读的顺序要一致。
像我这么爱(就)动(是)脑(懒)的人,是不喜欢这么做的。虽然提出用json来传的人是啥时候想的我是不知道的。
将对象转json(String格式的),因为string不是复杂格式,直接putStringExtra就行了(注意,只能传一条String数据),想要多条,我就ArrayList<String>了。再反过来想想,json是一种非常好的格式,既是一串字节(我们传递的String),又能准确的描述一个对象。
写这篇,只是想写点东西,而且再次加深自己的一个意识:返璞归真的去思考问题,能够获得更多。
- 浅谈Android中的序列化
- 浅谈Android序列化
- 浅谈Android序列化
- 浅谈Java中的序列化
- 浅谈对象中的成员序列化问题
- 浅谈 Java 中的对象序列化
- Android中的序列化
- android中的序列化
- Android中的序列化
- Android中的序列化
- Android 浅谈序列化Parcelable的使用
- Android 序列化 Parcelable和Serializable 浅谈
- Android中的序列化浅析
- Android中的序列化浅析
- Android中的序列化浅析
- Android中的序列化操作
- Android中的序列化方式
- Android 中的对象序列化
- 欢迎使用CSDN-markdown编辑器
- Android资源管理框架(Asset Manager)简要介绍和学习计划
- arc engineKML转Layer
- Android屏幕适配
- javaBean为什么要实现 序列化 Serializable接口?
- 浅谈Android中的序列化
- 如何写一个计算器?
- RadioGroup的简单封装
- UITableViewCell的选中时的颜色设置
- Docker: Error starting container: Unable to load the AUFS module
- iOS 摇一摇 实现
- 缓存jar包来提升spark on Yarn job的提交速度
- 【IOS】dataToHexString与hexStringToData
- 关于Servlet的生命周期与工作原理