Benefit of using Parcelable instead of serializing object

38,136

Solution 1

From "Pro Android 2"

NOTE: Seeing Parcelable might have triggered the question, why is Android not using the built-in Java serialization mechanism? It turns out that the Android team came to the conclusion that the serialization in Java is far too slow to satisfy Android’s interprocess-communication requirements. So the team built the Parcelable solution. The Parcelable approach requires that you explicitly serialize the members of your class, but in the end, you get a much faster serialization of your objects.

Also realize that Android provides two mechanisms that allow you to pass data to another process. The first is to pass a bundle to an activity using an intent, and the second is to pass a Parcelable to a service. These two mechanisms are not interchangeable and should not be confused. That is, the Parcelable is not meant to be passed to an activity. If you want to start an activity and pass it some data, use a bundle. Parcelable is meant to be used only as part of an AIDL definition.

Solution 2

Serializable is comically slow on Android. Borderline useless in many cases in fact.

Parcel and Parcelable are fantastically quick, but its documentation says you must not use it for general-purpose serialization to storage, since the implementation varies with different versions of Android (i.e. an OS update could break an app which relied on it).

The best solution for the problem of serializing data to storage at a reasonable speed is to roll your own. I personally use one of my own utility classes which has a similar interface to Parcel and which can serialize all the standard types very efficiently (at the expense of type safety). Here's an abridged version of it :

public interface Packageable {
    public void readFromPackage(PackageInputStream in)  throws IOException ;
    public void writeToPackage(PackageOutputStream out)  throws IOException ; 
}


public final class PackageInputStream {

    private DataInputStream input;

    public PackageInputStream(InputStream in) {
        input = new DataInputStream(new BufferedInputStream(in));
    }

    public void close() throws IOException {
        if (input != null) {
            input.close();
            input = null;
        }       
    }

    // Primitives
    public final int readInt() throws IOException {
        return input.readInt();
    }
    public final long readLong() throws IOException {
        return input.readLong();
    }
    public final long[] readLongArray() throws IOException {
        int c = input.readInt();
        if (c == -1) {
            return null;
        }
        long[] a = new long[c];
        for (int i=0 ; i<c ; i++) {
            a[i] = input.readLong();
        }
        return a;
    }

...

    public final String readString()  throws IOException {
        return input.readUTF();
    }
    public final <T extends Packageable> ArrayList<T> readPackageableList(Class<T> clazz) throws IOException {
        int N = readInt();
        if (N == -1) {
            return null;
        }
        ArrayList<T> list = new ArrayList<T>();
        while (N>0) {
            try {
                T item = (T) clazz.newInstance();
                item.readFromPackage(this);
                list.add(item);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            N--;
        }
        return list;
    }

}



public final class PackageOutputStream {

    private DataOutputStream output;

    public PackageOutputStream(OutputStream out) {
        output = new DataOutputStream(new BufferedOutputStream(out));
    }

    public void close() throws IOException {
        if (output != null) {
            output.close();
            output = null;
        }
    }

    // Primitives
    public final void writeInt(int val) throws IOException {
        output.writeInt(val);
    }
    public final void writeLong(long val) throws IOException {
        output.writeLong(val);
    }
    public final void writeLongArray(long[] val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        writeInt(val.length);
        for (int i=0 ; i<val.length ; i++) {
            output.writeLong(val[i]);
        }
    }

    public final void writeFloat(float val) throws IOException {
        output.writeFloat(val);
    }
    public final void writeDouble(double val) throws IOException {
        output.writeDouble(val);
    }
    public final void writeString(String val) throws IOException {
        if (val == null) {
            output.writeUTF("");
            return;
        }
        output.writeUTF(val);
    }

    public final <T extends Packageable> void writePackageableList(ArrayList<T> val) throws IOException {
        if (val == null) {
            writeInt(-1);
            return;
        }
        int N = val.size();
        int i=0;
        writeInt(N);
        while (i < N) {
            Packageable item = val.get(i);
            item.writeToPackage(this);
            i++;
        }
    }

}

Solution 3

See how fast Parcelable is than Serializable.


enter image description here

from WHY WE LOVE PARCELABLE


enter image description here

from Parcelable vs Serializable

Solution 4

If you need serialization for i.e. storage purposes but want to avoid the speed penalty of reflection incurred by the Serializable interface you should explicitly create your own serialization protocol with the Externalizable interface.

When properly implemented this matches the speed of Parcelable and also accounts for compatibility between different versions of Android and/or the Java platform.

This article might clear things up as well:

What is the difference between Serializable and Externalizable in Java?

On a sidenote, it is also the fastest serialization technique in many benchmarks, beating Kryo, Avro, Protocol Buffers and Jackson (json):

http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking

Solution 5

It seems that nowadays the difference isn't so noticeble, at least not when you run it between your own activities.

According to tests shown on this website , Parcelable is about 10 times faster on newest devices (like nexus 10), and is about 17 faster on old ones (like desire Z)

so it's up to you to decide if it worths it.

maybe for relatively small and simple classes, Serializable is fine, and for the rest, you should use Parcelable

Share:
38,136
Vladimir Ivanov
Author by

Vladimir Ivanov

Senior developer for mobile platforms at Kaspersky Lab.

Updated on July 08, 2022

Comments

  • Vladimir Ivanov
    Vladimir Ivanov almost 2 years

    As I understand, Bundle and Parcelable belongs to the way Android performs serialization in. It is used for example in passing data between activities. But I wonder, if there are any benefits in using Parcelable instead of classic serialization in case of saving state of my business objects to the internal memory for example? Will it be simpler or faster than the classic way? Where should I use classic serialization and where better to use bundles?

  • mparaz
    mparaz about 12 years
    Professional Android 2 Application Development by Reto Meier amazon.com/…
  • User
    User about 12 years
    The second paragraph is not true, you can pass a Parcelable as a parameter to an activity using the bundle...
  • Carrotman42
    Carrotman42 almost 12 years
    What is the difference between using this custom class of yours and just implementing the Externalizable interface and doing the same thing?
  • mikebabcock
    mikebabcock almost 12 years
    When I serialize my objects I create a getBundle method, then call that from writeToParcel as dest.writeBundle(getBundle()); and I have both options available in the object automatically. There are interesting Parcel features for live objects noted here: developer.android.com/reference/android/os/Parcel.html
  • mikebabcock
    mikebabcock almost 12 years
    Aren't you much better off using a Bundle which is type-safe to serialize your data? As noted above, you can pass a Bundle with a Parcel's writeBundle method.
  • Reuben Scratton
    Reuben Scratton almost 12 years
    Bundle serializes the field names as well... it's not suitable for thousands of objects.
  • Rise
    Rise over 11 years
    @lxx :I was wondering why one would need to pass an parcelable object through bundle to the activity. IMO if you do so you are adding one more level of serialization unnecessarily & nothing else.
  • Admin
    Admin over 11 years
    Sorry, inventing yet another serializer sucks - now there is just yet another "Parcelable" to deal with. There are plenty to choose from, with a library (the difference is the library is vetted, tested, and uses a format that other people use): ProtocolBuffers, JSON, XML, etc. It's a shame the Android library really sucks in this regard.
  • Reuben Scratton
    Reuben Scratton over 11 years
    I agree the situation sucks. My own lib for this is greatly expanded since the above answer was made, but it keeps lightning-fast binary serialization at its core. This works great for me because I particularly care about good performance, but what you gain in speed from this approach, you pay a small penalty for in flexibility. YMMV.
  • Pankaj
    Pankaj over 11 years
    @mikebabcock: And while reading from parcel, you use parc.readBundle(); and get every value from bundle and assign it to appropriate variable ? Just ti check if I am on right track :)
  • Jono
    Jono about 11 years
    In what examples would you wish to store a actual object in saya file system? Why not simply get the objects contents and store the actual contents in a file. Look at JSON for example or even xml. You can save objects in JSON or XML format, objects as in POJO/Entity types that construct a typical data object constructed with mostly States and getters and setters for that state. That way there is no need to serialize objects for the purpose of storing them as all you care about is the objects state
  • Vishy
    Vishy about 11 years
    Can you comment on how it differ from Extenalizable?
  • Aada
    Aada about 11 years
    Hope anyone to reply!! How come parcelable is not meant to be passed to an activity.. !!! Is that means we can't use parcelable class to pass teh object from one activity to another..??? Please someone reply
  • WonderCsabo
    WonderCsabo almost 11 years
    Philippe Breault made a nice article about this, and also added a performance test. developerphil.com/parcelable-vs-serializable
  • Wernight
    Wernight over 9 years
    A Parcelable has types defined in order, so unlike Bundle which is a key/value map, if the object changes, the Parcelable will fails badly. That's probably the main reason not to pass it to an Activity. I do wonder if the reverse it true (i.e., passing a Bundle to a Service).
  • Adam
    Adam over 9 years
    The "fast-serialization" library now works on Android and it pretty much blows everything else out of the water in terms of performance. Plus it works with the standard Serialization interface so it's usually a drop in solution for many projects: github.com/RuedigerMoeller/fast-serialization
  • Nemanja Kovacevic
    Nemanja Kovacevic over 9 years
    I don't think the opening sentence is true anymore (5 years after it was made). I've been using java serialization without any issues for a long time now. You can find some potentially interesting things on this topic in a blog post I've just written. nemanjakovacevic.net/blog/english/2015/03/24/…
  • Nemanja Kovacevic
    Nemanja Kovacevic over 9 years
    I think you're right on the money saying the difference is shrinking. However I found out that using serializable can be much more efficient in terms of size of marshaled byte array and that can help avoid TransactionTooLargeException. I would love to hear your comments on this (mine) blog post nemanjakovacevic.net/blog/english/2015/03/24/…
  • android developer
    android developer over 9 years
    Well, you could just put the huge memory consuming object on a static variable, and set it to null right when you fetch it (on onCreate for example). The disadvantage is that it doesn't support multi-processes, and it's a bit dirty way to do it. Wonder if that's the case if you wish to pass a large bitmap.
  • Reuben Scratton
    Reuben Scratton over 9 years
    Yep, it's not really such an issue any more. I've used nothing more than Serializable (with optimized readObject/writeObject implementations) for several years. In fact I looked at a hex dump of a few serialized objects only a few days ago and was satisfied it wasn't too wasteful.
  • Nickmccomb
    Nickmccomb about 7 years
    This is fine for small objects, not so much when you have large arrays of objects with a lot of properties in each.