精华内容
下载资源
问答
  • 序列化与反序列 ...在此过程中,先将对象的公共字段私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同
  • Android通过Parcelable和Serializable实现各种类型嵌套序列化
  • 1.Serializable 是java的序列化技术,最简单的使用方式为在需要序列化的class增加implements Serializable,并增加一个唯一个序列化id: private static final long serialVersionUID = 1L;默认方式最好直接设置为1L...

    一、Seralizable

    1.Serializable 是java的序列化技术,最简单的使用方式为在需要序列化的class增加implements Serializable,并增加一个唯一个序列化id: private static final long serialVersionUID = 1L; 默认方式最好直接设置为1L,因为java  sdk会自动进行hash计算,并生成唯一的UID值。手动设置serialVersionUID的好处是当前class如果改变了成员变量,比如增加或者删除之后,这个UID是不改变的,那么反序列化就不会失败;自动设置则在改变了成员变量之后就会重新计算获得新的UID,从而导致失败。

    2.Seralizable相对Parcelable而言,好处就是非常简单,只需对需要序列化的类class执行就可以,不需要手动去处理序列化和反序列化的过程,所以常常用于网络请求数据处理,Activity之间传递值的使用。

    3.Seralizable无法序列化静态变量,使用transient修饰的对象也无法序列化。

    4.当一个父类实现序列化,子类自动实现序列化,不需要再显示实现Serializable接口。

    二、Parcelable:

    1.Parcelable是android特有的序列化API,它的出现是为了解决Serializable在序列化的过程中消耗资源严重的问题,但是因为本身使用需要手动处理序列化和反序列化过程,会与具体的代码绑定,使用较为繁琐,一般只获取内存数据的时候使用。

    2.而Parcelable依赖于Parcel,Parcel的意思是包装,实现原理是在内存中建立一块共享数据块,序列化和反序列化均是操作这一块的数据,如此来实现。

    三、不同点:

    Serializalbe会使用反射,序列化和反序列化过程需要大量I/O操作,Parcelable自已实现封送和解封(marshalled &unmarshalled)操作不需要用反射,数据也存放在Native内存中,效率要快很多。

    Parcelable和Parcle这两者之间的关系?

    Parcelable 接口定义在封送/解封过程中混合和分解对象的契约。Parcelable接口的底层是Parcel容器对象。Parcel类是一种最快的序列化/反序列化机制,专为Android中的进程间通信而设计。该类提供了一些方法来将成员容纳到容器中,以及从容器展开成员。

    现在我们知道了如何传递自定义的对象,那么在两个Activity之前传递对象还要注意什么呢?

    一定要要注意对象的大小,Intent中的Bundle是在使用Binder机制进行数据传递的,能使用的Binder的缓冲区是有大小限制的(有些手机是2M),而一个进程默认有16个binder线程,所以一个线程能占用的缓冲区就更小了(以前做过测试,大约一个线程可以占用128KB)。所以当你看到“The Binder transaction failed because it was too large.”这类TransactionTooLargeException异常时,你应该知道怎么解决了。

     

    参考:https://blog.csdn.net/hacker_crazy/article/details/80840868

               https://www.jianshu.com/p/be593134eeae

    展开全文
  • Parcelable Serializable的区别使用

    万次阅读 2018-06-28 15:04:20
    一、Seralizable介绍:1.Serializable 是java的序列化技术,最简单的使用方式为在需要序列化的class增加implements Serializable,并增加一个唯一个序列化id: private static final long serialVersionUID = 1L;...

    序列化:为了保存在内存中的各种对象的状态,并可以把保存的对象的状态读出来。

    一、Seralizable介绍:

    1.Serializable 是java的序列化技术,最简单的使用方式为在需要序列化的class增加implements Serializable,并增加一个唯一个序列化id: private static final long serialVersionUID = 1L; 默认方式最好直接设置为1L,因为java  sdk会自动进行hash计算,并生成唯一的UID值。手动设置serialVersionUID的好处是当前class如果改变了成员变量,比如增加或者删除之后,这个UID是不改变的,那么反序列化就不会失败;自动设置则在改变了成员变量之后就会重新计算获得新的UID,从而导致失败。不过,大多数情况下两者都可以。

    2.Seralizable相对Parcelable而言,好处就是非常简单,只需对需要序列化的类class执行就可以,不需要手动去处理序列化和反序列化的过程,所以常常用于网络请求数据处理,Activity之间传递值的使用。

    Activiyt之间传递如图:




    3.Seralizable无法序列化静态变量,使用transient修饰的对象也无法序列化。

    4.当一个父类实现序列化,子类自动实现序列化,不需要再显示实现Serializable接口。

    二、Parcelable介绍:

    1.Parcelable是android特有的序列化API,它的出现是为了解决Serializable在序列化的过程中消耗资源严重的问题,但是因为本身使用需要手动处理序列化和反序列化过程,会与具体的代码绑定,使用较为繁琐,一般只获取内存数据的时候使用。

    2.而Parcelable依赖于Parcel,Parcel的意思是包装,实现原理是在内存中建立一块共享数据块,序列化和反序列化均是操作这一块的数据,如此来实现。


    3.Parcelable的三个过程:序列化、反序列化和描述

    序列化:

    @Override
        public void writeToParcel(Parcel dest, int flags) {
    
        }

    反序列化:

    class User{
    
        }
    
        public static final Creator<User> CREATOR = new Creator<User>() {
            @Override
            public User createFromParcel(Parcel source) {
                return null;
            }
    
            @Override
            public User[] newArray(int size) {
                return new User[0];
            }
        };

    描述:

    @Override
        public int describeContents() {
            return 0;
        }

    序列化的时候使用:writeXX

    反序列化的时候使用:readXX

    描述describecontents:


    一般情况下设置为0,特别的为

    public static final int CONTENTS_FILE_DESCRIPTOR = 0x0001;

    这种是当要求为file descriptor(文件描述符)被序列化的情况。


    【参考文档】:

    https://developer.android.com/reference/android/os/Parcelable

    http://www.developerphil.com/parcelable-vs-serializable/

    https://blog.csdn.net/Justin_1107/article/details/72903006



    展开全文
  • 序列化与反序列化之Parcelable和Serializable浅析

    万次阅读 多人点赞 2016-09-26 15:50:41
      一个对象要实现序列化操作,该类就必须实现了Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象类,而Parcelable接口则是android中特有的序列化接口,在某些情况下,Parcelable...

    转载请注明出处(万分感谢!):
    http://blog.csdn.net/javazejian/article/details/52665164
    出自【zejian的博客】

    本篇小部分内容摘自android开发艺术探索

      在日常的应用开发中,我们可能需要让某些对象离开内存空间,存储到物理磁盘,以便长期保存,同时也能减少对内存的压力,而在需要时再将其从磁盘读取到内存,比如将某个特定的对象保存到文件中,隔一段时间后再把它读取到内存中使用,那么该对象就需要实现序列化操作,在java中可以使用Serializable接口实现对象的序列化,而在android中既可以使用Serializable接口实现对象序列化也可以使用Parcelable接口实现对象序列化,但是在内存操作时更倾向于实现Parcelable接口,这样会使用传输效率更高效。接下来我们将分别详细地介绍这样两种序列化操作~~~~。

    序列化与反序列

    首先来了解一下序列化与反序列化。

    • 序列化

      由于存在于内存中的对象都是暂时的,无法长期驻存,为了把对象的状态保持下来,这时需要把对象写入到磁盘或者其他介质中,这个过程就叫做序列化。

    • 反序列化

      反序列化恰恰是序列化的反向操作,也就是说,把已存在在磁盘或者其他介质中的对象,反序列化(读取)到内存中,以便后续操作,而这个过程就叫做反序列化。

      概括性来说序列化是指将对象实例的状态存储到存储媒体(磁盘或者其他介质)的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换为字节流,然后再把字节流写入数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本。

    • 实现序列化的必要条件

      一个对象要实现序列化操作,该类就必须实现了Serializable接口或者Parcelable接口,其中Serializable接口是在java中的序列化抽象类,而Parcelable接口则是android中特有的序列化接口,在某些情况下,Parcelable接口实现的序列化更为高效,关于它们的实现案例我们后续会分析,这里只要清楚知道实现序列化操作时必须实现Serializable接口或者Parcelable接口之一即可。

    • 序列化的应用情景

      主要有以下情况(但不限于以下情况)

    • 1)内存中的对象写入到硬盘;
    • 2)用套接字在网络上传送对象;
    • 3)通过RMI(Remote Method Invoke 远程方法调用)传输对象;

      接下来我们分别介绍两种序列化的实现方式

    Serializable

      Serializable是java提供的一个序列化接口,它是一个空接口,专门为对象提供标准的序列化和反序列化操作,使用Serializable实现类的序列化比较简单,只要在类声明中实现Serializable接口即可,同时强烈建议声明序列化标识。如下:

    package com.zejian.ipctest;
    
    import java.io.Serializable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Client implements Serializable{
    
        /**
         * 生成序列号标识
         */
        private static final long serialVersionUID = -2083503801443301445L;
    
        private int id;
        private String name;
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

      如上述代码所示,Client类实现的Serializable接口并声明了序列化标识serialVersionUID,该ID由编辑器生成,当然也可以自定义,如1L,5L,不过还是建议使用编辑器生成唯一标识符。那么serialVersionUID有什么作用呢?实际上我们不声明serialVersionUID也是可以的,因为在序列化过程中会自动生成一个serialVersionUID来标识序列化对象。既然如此,那我们还需不需要要指定呢?由于serialVersionUID是用来辅助序列化和反序列化过程的,原则上序列化后的对象中serialVersionUID只有和当前类的serialVersionUID相同才能够正常被反序列化,也就是说序列化与反序列化的serialVersionUID必须相同才能够使序列化操作成功。具体过程是这样的:序列化操作的时候系统会把当前类的serialVersionUID写入到序列化文件中,当反序列化时系统会去检测文件中的serialVersionUID,判断它是否与当前类的serialVersionUID一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。报出如下UID错误:

    Exception in thread "main" java.io.InvalidClassException: com.zejian.test.Client; 
    local class incompatible: stream classdesc serialVersionUID = -2083503801443301445, 
    local class serialVersionUID = -4083503801443301445

      因此强烈建议指定serialVersionUID,这样的话即使微小的变化也不会导致crash的出现,如果不指定的话只要这个文件多一个空格,系统自动生成的UID就会截然不同的,反序列化也就会失败。ok~,了解这么多,下面来看一个如何进行对象序列化和反序列化的列子:

    package com.zejian.ipctest;
    
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Stest {
    
        public static void main(String[] args) throws Exception {
    
            //把对象序列化到文件
            Client client = new Client();
            client.setId(000001);
            client.setName("client");
    
            ObjectOutputStream oo = new ObjectOutputStream
                    (new FileOutputStream("/Users/zejian/Desktop/cache.txt"));
            oo.writeObject(client);
            oo.close();
    
            //反序列化到内存
            ObjectInputStream oi = new ObjectInputStream
                (new FileInputStream("/Users/zejian/Desktop/cache.txt"));
            Client c_back = (Client) oi.readObject();
            System.out.println("Hi, My name is " + c_back.getName());
            oi.close();
    
        }
    }

      从代码可以看出只需要ObjectOutputStream和ObjectInputStream就可以实现对象的序列化和反序列化操作,通过流对象把client对象写到文件中,并在需要时恢复c_back对象,但是两者并不是同一个对象了,反序列化后的对象是新创建的。这里有两点特别注意的是如果反序列类的成员变量的类型或者类名,发生了变化,那么即使serialVersionUID相同也无法正常反序列化成功。其次是静态成员变量属于类不属于对象,不会参与序列化过程,使用transient关键字标记的成员变量也不参与序列化过程。
      关键字transient,这里简单说明一下,Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。
      另外,系统的默认序列化过程是可以改变的,通过实现如下4个方法,即可以控制系统的默认序列化和反序列过程:

    package com.zejian.ipctest;
    
    import java.io.IOException;
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class Client implements Serializable{
    
        /**
         * 生成序列号标识
         */
        private static final long serialVersionUID = -4083503801443301445L;
    
    
        private int id;
        private String name;
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    
        /**
         * 序列化时,
         * 首先系统会先调用writeReplace方法,在这个阶段,
         * 可以进行自己操作,将需要进行序列化的对象换成我们指定的对象.
         * 一般很少重写该方法
         * @return
         * @throws ObjectStreamException
         */
        private Object writeReplace() throws ObjectStreamException {
            System.out.println("writeReplace invoked");
            return this;
        }
        /**
         *接着系统将调用writeObject方法,
         * 来将对象中的属性一个个进行序列化,
         * 我们可以在这个方法中控制住哪些属性需要序列化.
         * 这里只序列化name属性
         * @param out
         * @throws IOException
         */
        private void writeObject(java.io.ObjectOutputStream out) throws IOException {
            System.out.println("writeObject invoked");
            out.writeObject(this.name == null ? "zejian" : this.name);
        }
    
        /**
         * 反序列化时,系统会调用readObject方法,将我们刚刚在writeObject方法序列化好的属性,
         * 反序列化回来.然后通过readResolve方法,我们也可以指定系统返回给我们特定的对象
         * 可以不是writeReplace序列化时的对象,可以指定其他对象.
         * @param in
         * @throws IOException
         * @throws ClassNotFoundException
         */
        private void readObject(java.io.ObjectInputStream in) throws IOException,
                ClassNotFoundException {
            System.out.println("readObject invoked");
            this.name = (String) in.readObject();
            System.out.println("got name:" + name);
        }
    
    
        /**
         * 通过readResolve方法,我们也可以指定系统返回给我们特定的对象
         * 可以不是writeReplace序列化时的对象,可以指定其他对象.
         * 一般很少重写该方法
         * @return
         * @throws ObjectStreamException
         */
        private Object readResolve() throws ObjectStreamException {
            System.out.println("readResolve invoked");
            return this;
        }
    }

      通过上面的4个方法,我们就可以随意控制序列化的过程了,由于在大部分情况下我们都没必要重写这4个方法,因此这里我们也不过介绍了,只要知道有这么一回事就行。ok~,对于Serializable的介绍就先到这里。

    Parcelable

      鉴于Serializable在内存序列化上开销比较大,而内存资源属于android系统中的稀有资源(android系统分配给每个应用的内存开销都是有限的),为此android中提供了Parcelable接口来实现序列化操作,Parcelable的性能比Serializable好,在内存开销方面较小,所以在内存间数据传输时推荐使用Parcelable,如通过Intent在activity间传输数据,而Parcelable的缺点就使用起来比较麻烦,下面给出一个Parcelable接口的实现案例,大家感受一下:

    package com.zejian.ipctest;
    import android.os.Parcel;
    import android.os.Parcelable;
    
    /**
     * Created by zejian
     * Time 2016/9/25.
     * Description:
     */
    public class NewClient implements Parcelable {
    
        public int id;
        public String name;
        public User user;
    
        /**
         * 当前对象的内容描述,一般返回0即可
         * @return
         */
        @Override
        public int describeContents() {
            return 0;
        }
    
        /**
         * 将当前对象写入序列化结构中
         * @param dest
         * @param flags
         */
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(this.id);
            dest.writeString(this.name);
            dest.writeParcelable(this.user,0);
        }
    
        public NewClient() {
        }
    
        /**
         * 从序列化后的对象中创建原始对象
         * @param in
         */
        protected NewClient(Parcel in) {
            this.id = in.readInt();
            this.name = in.readString();
           //User是另一个序列化对象,此方法序列需要传递当前线程的上下文类加载器,否则会报无法找到类的错误
           this.user=in.readParcelable(Thread.currentThread().getContextClassLoader());
        }
    
        /**
         * public static final一个都不能少,内部对象CREATOR的名称也不能改变,必须全部大写。
         * 重写接口中的两个方法:
         * createFromParcel(Parcel in) 实现从Parcel容器中读取传递数据值,封装成Parcelable对象返回逻辑层,
         * newArray(int size) 创建一个类型为T,长度为size的数组,供外部类反序列化本类数组使用。
         */
        public static final Parcelable.Creator<NewClient> CREATOR = new Parcelable.Creator<NewClient>() {
            /**
             * 从序列化后的对象中创建原始对象
             */
            @Override
            public NewClient createFromParcel(Parcel source) {
                return new NewClient(source);
            }
    
            /**
             * 创建指定长度的原始对象数组
             * @param size
             * @return
             */
            @Override
            public NewClient[] newArray(int size) {
                return new NewClient[size];
            }
        };
    }

      从代码可知,在序列化的过程中需要实现的功能有序列化和反序列以及内容描述。其中writeToParcel方法实现序列化功能,其内部是通过Parcel的一系列write方法来完成的,接着通过CREATOR内部对象来实现反序列化,其内部通过createFromParcel方法来创建序列化对象并通过newArray方法创建数组,最终利用Parcel的一系列read方法完成反序列化,最后由describeContents完成内容描述功能,该方法一般返回0,仅当对象中存在文件描述符时返回1。同时由于User是另一个序列化对象,因此在反序列化方法中需要传递当前线程的上下文类加载器,否则会报无法找到类的错误。
      简单用一句话概括来说就是通过writeToParcel将我们的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成我们的对象。也可以将Parcel看成是一个类似Serliazable的读写流,通过writeToParcel把对象写到流里面,在通过createFromParcel从流里读取对象,这个过程需要我们自己来实现并且写的顺序和读的顺序必须一致。ok~,到此Parcelable接口的序列化实现基本介绍完。
      那么在哪里会使用到Parcelable对象呢?其实通过Intent传递复杂类型(如自定义引用类型数据)的数据时就需要使用Parcelable对象,如下是日常应用中Intent关于Parcelable对象的一些操作方法,引用类型必须实现Parcelable接口才能通过Intent传递,而基本数据类型,String类型则可直接通过Intent传递而且Intent本身也实现了Parcelable接口,所以可以轻松地在组件间进行传输。

    方法名称含义
    putExtra(String name, Parcelable value)设置自定义类型并实现Parcelable的对象
    putExtra(String name, Parcelable[] value)设置自定义类型并实现Parcelable的对象数组
    public Intent putParcelableArrayListExtra(String name, ArrayList value)设置List数组,其元素必须是实现了Parcelable接口的数据

      除了以上的Intent外系统还为我们提供了其他实现Parcelable接口的类,再如Bundle、Bitmap,它们都是可以直接序列化的,因此我们可以方便地使用它们在组件间进行数据传递,当然Bundle本身也是一个类似键值对的容器,也可存储Parcelable实现类,其API方法跟Intent基本相似,由于这些属于android基础知识点,这里我们就不过多介绍了。

    Parcelable 与 Serializable 区别

    • 两者的实现差异
        Serializable的实现,只需要实现Serializable接口即可。这只是给对象打了一个标记(UID),系统会自动将其序列化。而Parcelabel的实现,不仅需要实现Parcelabel接口,还需要在类中添加一个静态成员变量CREATOR,这个变量需要实现 Parcelable.Creator 接口,并实现读写的抽象方法。

    • 两者的设计初衷
        Serializable的设计初衷是为了序列化对象到本地文件、数据库、网络流、RMI以便数据传输,当然这种传输可以是程序内的也可以是两个程序间的。而Android的Parcelable的设计初衷是由于Serializable效率过低,消耗大,而android中数据传递主要是在内存环境中(内存属于android中的稀有资源),因此Parcelable的出现为了满足数据在内存中低开销而且高效地传递问题。

    • 两者效率选择
        Parcelable的性能比Serializable好,在内存开销方面较小,所以Android应用程序在内存间数据传输时推荐使用Parcelable,如activity间传输数据和AIDL数据传递,而Serializable将数据持久化的操作方便,因此在将对象序列化到存储设置中或将对象序列化后通过网络传输时建议选择Serializable(Parcelable也是可以,只不过实现和操作过程过于麻烦并且为了防止android版本不同而导致Parcelable可能不同的情况,因此在序列化到存储设备或者网络传输方面还是尽量选择Serializable接口)。

    • 两者需要注意的共同点
        无论是Parcelable还是Serializable,执行反序列操作后的对象都是新创建的,与原来的对象并不相同,只不过内容一样罢了。

    Android studio 中的快捷生成方式

    • Android studio 快捷生成Parcelable代码

      在程序开发过程中,我们实现Parcelable接口的代码都是类似的,如果我们每次实现一个Parcelable接口类,就得去编写一次重复的代码,这显然是不可取的,不过幸运的是,android studio 提供了自动实现Parcelable接口的方法的插件,相当实现,我们只需要打开Setting,找到plugin插件,然后搜索Parcelable插件,最后找到android Parcelable code generator 安装即可:
    这里写图片描述

    重启android studio后,我们创建一个User类,如下:

    这里写图片描述

    然后使用刚刚安装的插件协助我们生成实现Parcelable接口的代码,window快捷键:Alt+Insert,Mac快捷键:cmd+n,如下:

    这里写图片描述

    最后结果如下:

    这里写图片描述

    • Android studio 快捷生成Serializable的UID
        在正常情况下,AS是默认关闭serialVersionUID生成提示的,我们需要打开setting,找到检测(Inspections选项),开启 Serializable class without serialVersionUID 检测即可,如下:

    这里写图片描述

    然后新建User类实现Serializable接口,右侧会提示添加serialVersionUID,如下:

    这里写图片描述

    最后在类名上,Alt+Enter(Mac:cmd+Enter),快捷代码提示,生成serialVersionUID即可:

    这里写图片描述

    最终结果如下:
    这里写图片描述

    ok~,以上便是Parcelable与Serializable接口的全部内容,本篇结束。

    展开全文
  • 1)在使用内存的时候,ParcelableSerializable性能高,所以推荐使用Parcelable。 2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。 3)Parcelable不能使用在要将数据存储在磁盘上的...
     

     

    一、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; } }

    使用,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); // 传输方式一,intent直接调用putExtra // public Intent putExtra(String name, Serializable value) open.putExtra("put_ser_test", person); // 传输方式二,intent利用putExtras(注意s)传入bundle /** Bundle bundle = new Bundle(); bundle.putSerializable("bundle_ser",person); open.putExtras(bundle); */ startActivity(open); } }); } }

    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(); // 关键方法:getSerializableExtra ,我们的类是实现了Serializable接口的,所以写这个方法获得对象 // public class Person implements Serializable Person per = (Person)intent.getSerializableExtra("put_ser_test"); //Person per = (Person)intent.getSerializableExtra("bundle_ser"); mTvDate.setText("名字:"+per.getName()+"\n" +"年龄:"+per.getAge()); } }

    Serializable的序列化.gif

    Serializable 到此完成

    三、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); } }

    系统已经帮我们做了很多事情,我们需要做的很简单,就写写我们自己需要的构造方法,写一下私有变量的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; // 系统自动添加,给createFromParcel里面用 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; // 内容接口描述,默认返回0即可。 } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(color); // 写出 color dest.writeInt(size); // 写出 size } // ======分割线,写写get和set //个人自己添加 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; } }

    其实说起来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); // 传输方式一,intent直接调用putExtra // public Intent putExtra(String name, Serializable value) open.putExtra("put_ser_test", person); // 传输方式二,intent利用putExtras(注意s)传入bundle /** Bundle bundle = new Bundle(); bundle.putSerializable("bundle_ser",person); open.putExtras(bundle); */ startActivity(open); } }); // 采用Parcelable的方式 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); // public Intent putExtra(String name, Parcelable value) mTvOpenThird.putExtra("parcel_test",tranPen); startActivity(mTvOpenThird); } }); } }

    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); // Intent intent = getIntent(); // Pen pen = (Pen)intent.getParcelableExtra("parcel_test"); Pen pen = (Pen)getIntent().getParcelableExtra("parcel_test"); mTvThirdDate = (TextView) findViewById(R.id.mTvThirdDate); mTvThirdDate.setText("颜色:"+pen.getColor()+"\n" +"大小:"+pen.getSize()); } }

    Parcelable的方式.gif

    完成,Serializable 和Parcelable 这两种方式都介绍完成了。接下说一说对比

    四、Serializable 和Parcelable的对比

    android上应该尽量采用Parcelable,效率至上

    编码上:

    Parcelable代码量少,写起来方便

    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

    展开全文
  • 主要介绍了Android ParcelableSerializable详解及区别的相关资料,需要的朋友可以参考下
  • Parcelable和Serializable的区别-附件资源
  • https://blog.csdn.net/jdsjlzx/article/details/109064067
  • 1、实现Serializable接口 2、实现Parcelable接口   为什么要将对象序列化?  1、永久性保存对象,保存对象的字节序列到本地文件中;  2、用过序列化对象在网络中传递对象;  3、通过序列化...
  • 文章目录Serializable,简单Parcelable,高效 Serializable,简单 public class SerializableDeveloper implements Serializable String name; int yearsOfExperience; List<Skill> skillSet; float ...
  • 一、序列化与反序列化 由于在系统底层,数据的传输形式是简单的字节序列形式传递,即在底层,系统不认识对象,只认识字节序列,...有了以上理解,接下来我们认识两个用于序列化反序列化的接口:java原生的Seriali...
  • 另一篇介绍文章:https://greenrobot.me/devpost/android-parcelable-serializable/ 一、Android为什么要序列化?什么是序列化,怎么进行序列化 why 为什么要了解序列化?—— 进行Android开发的时候,无法将对象...
  • Android Parcelable和Serializable的区别

    万次阅读 2013-07-31 14:11:52
    本文主要介绍Parcelable和Serializable的作用、效率、区别及选择,关于Serializable的介绍见Java 序列化的高级认识。   1、作用 Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi...
  • ParcelableSerializable的性能比较 Parcelable Serizlizable 实现Parcelable接口 实现Serizlizable接口 android 专用 Java 自带 内存消耗:低 内存消耗:一般 内存中直接进行读写 通过使用IO流的...
  • Parcelable和Serializable

    2019-05-20 22:26:13
    通过parcel 实现了 多进程...1)在使用内存的时候,ParcelableSerializable性能高,所以推荐使用Parcelable。 2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC。 3)Parcelable不能...
  • 为对象提供一个序列化反序列化的操作。使用简单,只需要在类的申明中指定一个标记即可: Private static final long serialVersionUID = xxxxxxxxxxxxxxxxxxxx(注意:UID的可以根据当前类的结构自动去生成它的...
  • 本文主要介绍Parcelable和Serializable的作用、效率、区别及选择。 1、作用 Serializable的作用是为了保存对象的属性到本地文件、数据库、网络流、rmi以方 便数据传输,当然这种传输可以是程序内的也可以是两个...
  • ParcelableSerializable

    2016-09-19 15:58:56
    Parcelable序列化,intent传递对象

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,176
精华内容 4,870
关键字:

parcelable和serializable