【问题标题】:Android: Difference between Parcelable and Serializable?Android:Parcelable 和 Serializable 之间的区别?
【发布时间】:2011-03-20 09:08:05
【问题描述】:

为什么Android提供2个接口来序列化对象?可序列化对象是否与 Android Binder 和 AIDL 文件互操作?

【问题讨论】:

    标签: android parcelable serializable


    【解决方案1】:

    在 Android 中,我们不能只将对象传递给活动。为此,对象必须实现SerializableParcelable 接口。

    可序列化

    Serializable 是一个标准的 Java 接口。您可以只实现Serializable 接口并添加覆盖方法。这种方法的问题是使用了反射,而且这是一个缓慢的过程。此方法会创建大量临时对象并导致大量垃圾收集。不过Serializable接口更容易实现。

    看下面的例子(Serializable):

    // MyObjects Serializable class
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.TreeMap;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class MyObjects implements Serializable {
    
        private String name;
        private int age;
        public ArrayList<String> address;
    
        public MyObjects(String name, int age, ArrayList<String> address) {
            super();
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public ArrayList<String> getAddress() {
            if (!(address == null))
                return address;
            else
                return new ArrayList<String>();
        }
    
        public String getName() {
            return name;
        }
    
        // return age
        public int getAge() {
            return age;
        }
    }
    
    // MyObjects instance
    MyObjects mObjects = new MyObjects("name", "age", "Address array here");
    
    // Passing MyObjects instance via intent
    Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
    mIntent.putExtra("UniqueKey", mObjects);
    startActivity(mIntent);
    
    // Getting MyObjects instance
    Intent mIntent = getIntent();
    MyObjects workorder = (MyObjects)    mIntent.getSerializableExtra("UniqueKey");
    

    可打包

    Parcelable 进程比Serializable 快得多。造成这种情况的原因之一是我们对序列化过程是明确的,而不是使用反射来推断它。也有理由为此目的对代码进行了大量优化。

    看下面的例子(Parcelable):

    // MyObjects Parcelable class
    
    import java.util.ArrayList;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class MyObjects implements Parcelable {
    
        private int age;
        private String name;
        private ArrayList<String> address;
    
        public MyObjects(String name, int age, ArrayList<String> address) {
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public MyObjects(Parcel source) {
            age = source.readInt();
            name = source.readString();
            address = source.createStringArrayList();
        }
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(age);
            dest.writeString(name);
            dest.writeStringList(address);
        }
    
        public int getAge() {
            return age;
        }
    
        public String getName() {
            return name;
        }
    
        public ArrayList<String> getAddress() {
            if (!(address == null))
                return address;
            else
                return new ArrayList<String>();
        }
    
        public static final Creator<MyObjects> CREATOR = new Creator<MyObjects>() {
            @Override
            public MyObjects[] newArray(int size) {
                return new MyObjects[size];
            }
    
            @Override
            public MyObjects createFromParcel(Parcel source) {
                return new MyObjects(source);
            }
        };
    }
    
    // MyObjects instance
    MyObjects mObjects = new MyObjects("name", "age", "Address array here");
    
    // Passing MyOjects instance
    Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
    mIntent.putExtra("UniqueKey", mObjects);
    startActivity(mIntent);
    
    // Getting MyObjects instance
    Intent mIntent = getIntent();
    MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");
    

    您可以传递 ArrayList 的 Parcelable 对象,如下所示:

    // Array of MyObjects
    ArrayList<MyObjects> mUsers;
    
    // Passing MyOjects instance
    Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
    mIntent.putParcelableArrayListExtra("UniqueKey", mUsers);
    startActivity(mIntent);
    
    // Getting MyObjects instance
    Intent mIntent = getIntent();
    ArrayList<MyObjects> mUsers = mIntent.getParcelableArrayList("UniqueKey");
    

    结论

    1. ParcelableSerializable 接口快
    2. Serializable 接口相比,Parcelable 接口需要更多时间来实现
    3. Serializable接口更容易实现
    4. Serializable 接口会创建大量临时对象并导致大量垃圾回收
    5. Parcelable数组可以通过android中的Intent传递

    【讨论】:

    • @Sujith 你说的使用反射是什么意思?什么是反射
    • @AbhinavVutukuri 反射是在运行时通过 Object.getClass() 等检查对象、字段和方法的术语。
    • Serializables 更适合持久化数据,而 Parcelable 对象则根本不应该持久化。这是一个非常糟糕的做法
    • @Sujith 正如不止一个人所说,Parcelable 对象不能(可靠地)持久化,但 Serializable 对象可以(在限制范围内)。由于您的答案得分最高,并且给人的印象是涵盖了所有重要差异,因此您可能应该提及这一点。
    • 现在 Parcelable 的实现与 Serializable 一样快,只需在 Android Studio 中实现 Parcelable 的任何类上按 ALT + INSERT 即可。
    【解决方案2】:

    Serializable 是一个标准的 Java 接口。你只需通过实现接口来标记一个类Serializable,Java会在某些情况下自动序列化它。

    Parcelable 是您自己实现序列化的 Android 特定接口。它的创建比 Serializable 更有效,并解决了默认 Java 序列化方案的一些问题。

    我相信 Binder 和 AIDL 可以处理 Parcelable 对象。

    但是,您可以在 Intents 中使用 Serializable 对象。

    【讨论】:

    • 如何序列化 Parcelable 对象?如何让它持久化?
    • @Haded 获取对象状态的内容并将其存储在文件或 SQLLite 数据库中。序列化对于使对象可以在 android 中的不同组件或完全不同的应用程序之间传输非常有用。
    • 这是一个很好的解释。我还注意到:“Parcel 不是通用的序列化机制。这个类(以及用于将任意对象放入 Parcel 的相应 Parcelable API)被设计为高性能 IPC 传输。因此,它不适合将任何 Parcel 数据放入持久存储中:Parcel 中任何数据的底层实现发生变化都可能导致旧数据不可读。” developer.android.com/reference/android/os/Parcel.html
    • @Zhisheng 任意对象是什么意思?我们可以在 Parcel 中放入什么样的对象?
    • 用gson把对象转成json字符串怎么样?
    【解决方案3】:

    如果您想成为一个好公民,请花额外的时间来实施 Parcelable,因为它的执行速度会快 10 倍并且使用更少 资源。

    但是,在大多数情况下,Serializable 的缓慢性不会 显。随意使用它,但请记住序列化是 这是一项昂贵的操作,因此请尽量减少。

    如果您尝试传递包含数千个序列化对象的列表, 整个过程可能需要一秒钟以上。它 可以使从纵向到横向的过渡或旋转感觉非常好 迟钝。

    来源至此:http://www.developerphil.com/parcelable-vs-serializable/

    【讨论】:

    • 但是,在大多数情况下,Serializable 的缓慢并不明显。
    【解决方案4】:

    在 Parcelable 中,开发人员编写用于编组和解组的自定义代码,因此与序列化相比,它创建的垃圾对象更少。由于这种自定义实现,Parcelable over Serialization 的性能显着提高(大约快了两倍)。

    Serializable 是一个标记接口,这意味着用户不能根据他们的要求来编组数据。在序列化中,使用 Java 反射 API 在 Java 虚拟机 (JVM) 上执行编组操作。这有助于识别 Java 对象的成员和行为,但最终也会创建大量垃圾对象。 因此,序列化过程比 Parcelable 慢。

    编辑:编组和解组是什么意思?

    简而言之,“编组”是指将数据或对象转换为字节流的过程,而“解组”是将字节流转换回其原始数据或对象的逆过程。转换是通过“序列化”实现的。

    http://www.jguru.com/faq/view.jsp?EID=560072

    【讨论】:

    • 即使没有详细的示例,也可以很好地解释。正是我需要修改的。
    【解决方案5】:

    Parcelable 是 Android 开发中的一种标准。但不是因为速度

    Parcelable 是推荐的数据传输方法。但是如果你正确地使用了如this repo 所示的serializable,你会发现serializable 有时甚至比parcelable 还要快。或者至少时间是可比的。

    Parcelable 比 Serializable 更快吗?

    不,如果序列化正确完成。

    普通 Android 设备上的常规 Java 序列化(如果操作正确*)在写入方面比 Parcelable 快大约 3.6 倍,在读取方面大约快 1.6 倍。它还证明了 Java 序列化(如果做得好)是一种快速的存储机制,即使对于 11000 个对象(每个对象有 10 个字段)的相对较大的对象图,它也能提供可接受的结果。

    * 旁注是,通常每个盲目地说“Parcelable 更快”的人都会将其与默认的自动序列化进行比较,后者在内部使用了很多反射。这是不公平的比较,因为 Parcelable 使用手动(并且非常复杂)将数据写入流的过程。通常没有提到的是,根据文档的标准 Java Serializable 也可以使用 writeObject() 和 readObject() 方法以手动方式完成。有关详细信息,请参阅 JavaDocs。为了获得最佳性能,应该这样做。

    那么,如果 serializable 更快更容易实现,为什么 android 有 parcelable 呢?

    原因是本机代码。 Parcelable 的创建不仅仅是为了进程间通信。它也可以用于码间通信。您可以从 C++ 本机层发送和接收对象。就是这样。

    你应该选择什么?两者都会很好地工作。但我认为 Parcelable 是更好的选择,因为它是 google 推荐的,并且从这个线程中可以看出,它更受欢迎。

    【讨论】:

    • 你能找到你的资源吗?我真的很感激。谢谢!!
    • 我从从事 AOSP 相关项目 twitter.com/bwdude 的经验丰富的开发人员那里得到答案。他说,与 SDK 层通信的原生 C++ 代码使用自己的 Parcelable 实现。我猜他在谈论这门课android.googlesource.com/platform/frameworks/native/+/…我知道这不是最好的解释,但这是我目前最好的。如果您会发现其他内容,请务必在此处发布 =)
    • 希望我能不止一次地支持你。我看到优秀的 Android 和 Java 专家在这里寻求最受好评的答案。缺乏文档确实阻止了 Serializable 的任何风头。感觉就像这些是推广特定 API 的效果。谢谢!
    • 你能解释一下什么是代码间通信
    • 我猜那是你想在 c++ 和 java 之间进行通信的时候。不仅在java和java之间。
    【解决方案6】:

    我实际上将成为倡导可序列化的人。速度差异不再那么大,因为这些设备比几年前要好得多,而且还有其他更细微的差异。有关更多信息,请参阅 my blog 帖子以了解更多信息。

    【讨论】:

    • 感谢您的分享。实现可序列化不太复杂,需要在那些罕见和超优化的情况下做出权衡。
    • 另一种观点,尤其是在有实验和结果支持的情况下,非常有帮助。我必须使用很多现有的基于 Parcelable 的源代码,并且在我阅读了您的博客文章之后可能会重构其中的一些。
    【解决方案7】:

    1。可序列化

    @see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

    什么接口?

    • 是标准的Java接口

    速度

    • 比 Parcelable 慢

    2。可打包

    @see http://developer.android.com/reference/android/os/Parcelable.html

    什么接口?

    • 是android.os接口
      • 这意味着 Google 开发 Parcelable 是为了在 android 上获得更好的性能

    速度

    • 更快(因为它针对 android 开发的使用进行了优化)

    > 总结

    请注意,Serializable 是标准的 Java 接口,而 Parcelable 是用于 Android 开发的

    【讨论】:

    • 你也应该添加它们的用途。
    【解决方案8】:

    关于编组和解组存在一些性能问题。 Parcelable 比 Serializable 快两倍。

    请通过以下链接:

    http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development

    【讨论】:

    【解决方案9】:

    如果你在 android studio 中使用 paracelable 插件,parcelable 的实现会更快。搜索 Android Parcelable 代码生成器

    【讨论】:

      【解决方案10】:

      Serializable 接口可以像 Parcelable 接口一样使用,从而获得(不多)更好的性能。 只需覆盖这两种方法来处理手动编组和解组过程:

      private void writeObject(java.io.ObjectOutputStream out)
          throws IOException
      private void readObject(java.io.ObjectInputStream in)
          throws IOException, ClassNotFoundException
      

      不过,在我看来,在开发原生 Android 时,使用 Android api 是要走的路。

      见:

      【讨论】:

        【解决方案11】:

        Parcelable 比使用 Binder 可序列化快得多,因为可序列化使用反射并导致许多 GC。 Parcelable 是为了优化传递对象而设计的。

        这里是参考链接。 http://www.developerphil.com/parcelable-vs-serializable/

        【讨论】:

          【解决方案12】:

          您可以在意图中使用可序列化对象,但在序列化 Parcelable 对象时,它可能会引发严重的异常,例如 NotSerializableException。是否不建议将 Serializable 与 Parcelable 一起使用。因此,最好使用要与捆绑和意图一起使用的对象来扩展 Parcelable。由于这个 Parcelable 是 android 特定的,所以它没有任何副作用。 :)

          【讨论】:

            【解决方案13】:

            我回答迟了,但希望能对其他人有所帮助。

            速度方面,Parcelable &gt; Serializable。但是,Custom Serializable 是个例外。它几乎在 Parcelable 范围内,甚至更快。

            参考:https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/

            例子:

            要序列化的自定义类

            class MySerialized implements Serializable { 
            
                String deviceAddress = "MyAndroid-04"; 
            
                transient String token = "AABCDS"; // sensitive information which I do not want to serialize
            
                private void writeObject(ObjectOutputStream oos) throws Exception {
                    oos.defaultWriteObject();
                    oos.writeObject("111111" + token); // Encrypted token to be serialized
                }
            
                private void readObject(ObjectInputStream ois) throws Exception {
                    ois.defaultReadObject(); 
                    token = ((String) ois.readObject()).subString(6);  // Decrypting token
                }
            
            }
            

            【讨论】:

              【解决方案14】:

              可序列化

              Serializable 是一个可标记的接口,或者我们可以调用一个空接口。它没有任何预先实现的方法。 Serializable 将对象转换为字节流。因此,用户可以将一个活动之间的数据传递给另一个活动。 serializable 的主要优点是创建和传递数据非常容易,但与 parcelable 相比,这是一个缓慢的过程。

              可打包

              Parcelable 比可序列化更快。 Parcel 能够将对象转换为字节流并在两个活动之间传递数据。与序列化相比,编写可打包的代码有点复杂。在两个活动之间传递数据时,它不会创建更多临时对象。

              【讨论】:

              • Parcelable 比 serializable 更快。并非总是如此!
              猜你喜欢
              • 2015-12-20
              • 2011-05-31
              • 1970-01-01
              • 1970-01-01
              • 2011-09-20
              • 1970-01-01
              • 2011-05-13
              • 1970-01-01
              相关资源
              最近更新 更多