时间:2010-07-23 23:26:35

标签: android parcelable serializable

15 个答案:

答案 0 :(得分:390)

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

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. 更快 与Parcelable interface 相比,
  3. Serializable接口需要更多时间来实现
  4. Serializable界面更易于实施
  5. Serializable接口会创建大量临时对象并导致相当多的垃圾回收
  6. Parcelable数组可以通过android中的Intent传递

答案 1 :(得分:171)

答案 2 :(得分:36)

  

如果你想成为一个好公民,请花些额外的时间来实施   可分辨,因为它将执行速度提高10倍并且使用更少   资源。

     

但是,在大多数情况下,Serializable的速度不会很慢   显。随意使用它,但请记住序列化   这是一项昂贵的操作,所以要尽量减少。

     

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

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

答案 3 :(得分:30)

Parcelable vs Serializable 我推荐这两个。

可序列化,简洁

  

什么是Serializable?

     

Serializable是标准的Java接口。它不是一部分   Android SDK。它的简洁是它的美丽。只是实现这一点   界面你的POJO将准备从一个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;
}
}
  • serializable的美妙之处在于您只需要在类及其子类上实现Serializable接口。它是一个标记接口,意味着没有方法可以实现,Java将尽最大努力有效地序列化它。

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

Parcelable,The Speed

  

什么是Parcelable?

     

Parcelable是另一个界面。尽管它的竞争对手(Serializable in   如果您忘了),它是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];
    }
};
}

现在,获胜者是

enter image description here

Philippe Breault进行的测试结果表明,Parcelable比Serializable快10倍以上。其他一些Google工程师也支持这一陈述。

  

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

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

  

现在,还有另一种方法。 Serializable背后的整个自动过程可以用自定义代码替换,该代码使用writeObject()&amp;   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;

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

答案 4 :(得分:27)

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

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

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

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

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

答案 5 :(得分:16)

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

答案 6 :(得分:11)

1。序列化

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

什么界面?

  • 是标准的Java接口

速度

  • 比Parcelable慢

2。 Parcelable

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

什么界面?

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

速度

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

&GT;结论

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

答案 7 :(得分:6)

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

请浏览以下链接:

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

答案 8 :(得分:4)

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

答案 9 :(得分:2)

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

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

可拆分的速度比可序列化的速度快吗?

  

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

     

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

因此,如果可序列化的速度更快且更容易实现,为什么android可以完全打包?

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

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

答案 10 :(得分:1)

您可以在意图中使用可序列化对象,但在序列化Parcelable对象时,它可能会产生严重的异常,如NotSerializableException。是否建议使用可序列化的Parcelable。因此,最好将Parcelable扩展为要与bundle和Intent一起使用的对象。因为这个Parcelable是特定于Android的,所以它没有任何副作用。 :)

答案 11 :(得分:1)

Serializable接口的使用方法与Parcelable接口的使用方式相同,可以获得更好的性能。 只需覆盖这两种方法来处理手动编组和解组过程:

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

尽管如此,在我看来,在开发原生Android时,使用Android api是可行的方法。

见:

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

可序列化

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

可包裹

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

答案 14 :(得分:0)

我的回答很晚,但是希望能对其他人有所帮助。

根据速度Parcelable > 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
    }

}