Android:Parcelable和Serializable之间的区别?

liv*_*m95 289 android serializable parcelable

为什么Android提供了2个用于序列化对象的接口?Serializable对象是否与Android Binder和AIDL文件进行交互?

Suj*_*ith 415

在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;
    }

    public String getAge() {
        return age;
    }
}
Run Code Online (Sandbox Code Playgroud)
// 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);
Run Code Online (Sandbox Code Playgroud)
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects)    mIntent.getSerializableExtra("UniqueKey");
Run Code Online (Sandbox Code Playgroud)

Parcelable

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);
        }
    };
}
Run Code Online (Sandbox Code Playgroud)
// 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);
Run Code Online (Sandbox Code Playgroud)
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");
Run Code Online (Sandbox Code Playgroud)

您可以传递ArrayListParcelable对象,如下所示:

// Array of MyObjects
ArrayList<MyObjects> mUsers;

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

结论

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

  • @AbhinavVutukuri Reflection是在运行时通过Object.getClass()等检查对象,字段和方法的术语. (11认同)
  • @Sujith *使用反射*是什么意思?什么是“反射”? (2认同)
  • Serializables更适合持久化数据,另一方面,parcelable对象根本不应该持久化.这是一个非常糟糕的做法 (2认同)
  • @Sujith正如不止一个人所说,Parcelable对象不能持久(可靠),但Serializable可以(在限制范围内).既然你的答案得分最高并且给人的印象就是涵盖所有重要的差异,你应该提到这一点. (2认同)
  • 现在,Parcelable的实现与Serializable一样快,只需在Android Studio中任何实现Parcelable的类上按ALT + INSERT,IDE就会做到。 (2认同)

Che*_*mon 177

Serializable是标准的Java接口.您只需通过实现接口标记Serializable类,Java将在某些情况下自动序列化它.

Parcelable是一个Android特定的界面,您可以自己实现序列化.它被创建为比Serializable更高效,并解决了默认Java序列化方案的一些问题.

我相信Binder和AIDL使用Parcelable对象.

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

  • 这是一个很好的解释.我也注意到这一点:"Parcel不是一个通用的序列化机制.这个类(以及用于将任意对象放入Parcel的相应Parcelable API)被设计为高性能的IPC传输.因此,它不适合将任何Parcel数据放入持久存储中:Parcel中任何数据的基础实现的更改都可能导致旧数据不可读." http://developer.android.com/reference/android/os/Parcel.html (6认同)

Far*_*ana 40

Parcelable vs Serializable我指的是这两个.

Serializable,简单

什么是Serializable?

Serializable是标准的Java接口.它不是Android SDK的一部分.它的简洁是它的美丽.只需实现此界面,您的POJO就可以从一个Activity跳转到另一个Activity.

public class TestModel implements Serializable {

String name;

public TestModel(String name) {
    this.name = name;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
  • serializable的美妙之处在于您只需要在类及其子类上实现Serializable接口.它是一个标记接口,意味着没有方法可以实现,Java将尽最大努力有效地序列化它.

  • 这种方法的问题在于使用反射并且这是一个缓慢的过程.这种机制也倾向于创建大量临时对象并导致相当多的垃圾收集.

Parcelable,The Speed

什么是Parcelable?

Parcelable是另一个界面.尽管它是竞争对手(Serializable,如果你忘了),它是Android SDK的一部分.现在,Parcelable是专门设计的,使用它时没有反射.那是因为我们对序列化过程非常明确.

public class TestModel implements Parcelable {


String name;

public TestModel(String name, String id) {
    this.name = name;
}

protected TestModel(Parcel in) {
    this.name = in.readString();


}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeString(this.name);

}

public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() {
    @Override
    public TestModel createFromParcel(Parcel source) {
        return new TestModel(source);
    }

    @Override
    public TestModel[] newArray(int size) {
        return new TestModel[size];
    }
};
}
Run Code Online (Sandbox Code Playgroud)

现在,获胜者是

在此输入图像描述

Philippe Breault进行的测试结果表明,Parcelable比Serializable快10倍以上.其他一些谷歌工程师也支持这一声明.

据他们说,默认的Serializable方法比Parcelable慢.在这里,我们双方达成协议!但是,完全比较这两个是不公平的!因为使用Parcelable,我们实际上是在编写自定义代码.专门为那个POJO创建的代码.因此,不会产生垃圾,结果会更好.但是使用默认的Serializable方法,我们依赖于Java的自动序列化过程.这个过程显然不是自定义的,会产生大量垃圾!因此,结果更糟.

停止!!!!,在做出决定之前

现在,还有另一种方法.Serializable背后的整个自动过程可以由使用writeObject()和readObject()方法的自定义代码替换.这些方法是具体的.如果我们想要将Serializable方法与自定义序列化行为相结合,那么我们必须使用与下面相同的完全签名来包含这两个方法:

 private void writeObject(java.io.ObjectOutputStream out)
 throws IOException;

 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;

 private void readObjectNoData()
     throws ObjectStreamException;
Run Code Online (Sandbox Code Playgroud)

现在Parcelable和自定义Serializable之间的比较看起来很公平!结果可能会令人惊讶!与Parcelable相比,自定义Serializable方法的写入速度提高了3倍,读取速度提高了1.6倍.

  • 我很喜欢看书..谢谢 (2认同)

cod*_*cat 37

如果你想成为一个好公民,可以花些额外的时间来实现Parcelable,因为它的执行速度提高了10倍,并且使用的资源更少.

但是,在大多数情况下,Serializable的缓慢性并不明显.随意使用它,但请记住序列化是一项昂贵的操作,所以要尽量减少它.

如果您尝试传递包含数千个序列化对象的列表,则整个过程可能需要一秒钟以上.它可以使从肖像到景观的过渡或旋转感觉非常缓慢.

来源到这一点:http://www.developerphil.com/parcelable-vs-serializable/


Uts*_*Uts 29

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

序列化是一种标记接口,这意味着用户无法根据需要封送数据.在序列化中,使用Java反射API在Java虚拟机(JVM)上执行编组操作.这有助于识别Java对象的成员和行为,但最终还是会创建大量垃圾对象.因此,与Parcelable相比,序列化过程很慢.

编辑:编组和解组的含义是什么?

简而言之,"编组"是指将数据或对象转换为字节流的过程,"解组"是将字节流beack转换为其原始数据或对象的相反过程.转换是通过"序列化"实现的.

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

  • 即使没有详细的例子,也能很好地解释。正是我需要的修订。 (2认同)

Nem*_*vic 19

我实际上将成为一个倡导Serializable的人.速度差异不再那么激烈,因为这些设备比几年前要好得多,还有其他更微妙的差异.有关详细信息,请参阅在此问题上的博文.

  • 另一种观点,特别是在通过实验和结果支持时,非常有帮助.我必须使用许多现有的基于Parcelable的源代码,并且在我阅读你的博客文章后可能会重构其中一些. (2认同)

Mak*_*aev 12

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

建议使用Parcelable方法进行数据传输。但是,如果您如本存储库所示正确使用了可序列化,您将看到有时可序列化甚至比可打包更快。或者至少时间是可比的。

可打包的速度快于可序列化的速度吗?

在普通的Android设备上,通常的Java序列化(如果操作正确*)比Parcelable快3.6倍,而读取则快1.6倍。还证明了Java序列化(如果操作正确)是一种快速存储机制,即使在相对较大的对象图(包含11000个对象,每个对象包含10个字段)的情况下,也能给出可接受的结果。

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

那么,如果可序列化更快,更容易实现,为什么android完全具有可打包性?

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

您应该选择什么?两者都会很好地工作。但是我认为Parcelable是更好的选择,因为它是Google推荐的,并且您可以从此线程中看到它,这一点值得赞赏。

  • 你能找到你的来源吗?我真的很感激。谢谢!! (2认同)
  • 我从经验丰富的开发人员那里得到了这个答案,他从事AOSP相关项目https://twitter.com/bwdude。他说,用于与SDK层通信的本机C ++代码使用其自己的Parcelable实现。我猜他是在谈论此类课程https://android.googlesource.com/platform/frameworks/native/+/brillo-m10-dev/include/binder/Parcelable.h我知道这不是最好的解释,但是它是我目前拥有的最好的。如果您还有其他发现,请务必在此处发布=) (2认同)
  • 我想这就是你想要在c++和java之间进行通信的时候。不仅仅是java和java之间。 (2认同)

iti*_*skj 11

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接口
    • 这意味着谷歌开发了Parcelable以在Android上获得更好的性能

速度

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

>结论

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


小智 6

关于编组和解编有一些性能问题.Parcelable比Serializable快两倍.

请通过以下链接:

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