Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Benefit of using Parcelable instead of serializing object

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?

like image 925
Vladimir Ivanov Avatar asked Apr 05 '11 10:04

Vladimir Ivanov


People also ask

Why is it better to use Parcelable than serializable in Android?

Parcel able is faster than serializable. Parcel able is going to convert object to byte stream and pass the data between two activities. Writing parcel able code is little bit complex compare to serialization. It doesn't create more temp objects while passing the data between two activities.

Why do we use Parcelable in Android?

Parcelable and Bundle objects are intended to be used across process boundaries such as with IPC/Binder transactions, between activities with intents, and to store transient state across configuration changes.

What's the difference between serializable and Parcelable?

Serializable is a standard Java interface. You simply mark a class Serializable by implementing the interface, and Java will automatically serialize it in certain situations. Parcelable is an Android specific interface where you implement the serialization yourself.

Does Parcelable use reflection?

Unlike Serializable, in Parcelable reflection won't be used so it is faster and has better performance. Android Parcelabe is not made to save objects into the files, so if you want to save an object in the file you must use Serializable.


8 Answers

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.

like image 72
Rajath Avatar answered Oct 05 '22 21:10

Rajath


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

}
like image 25
Reuben Scratton Avatar answered Oct 05 '22 22:10

Reuben Scratton


See how fast Parcelable is than Serializable.


enter image description here

from WHY WE LOVE PARCELABLE


enter image description here

from Parcelable vs Serializable

like image 37
kenju Avatar answered Oct 05 '22 20:10

kenju


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

like image 21
whitebrow Avatar answered Oct 05 '22 21:10

whitebrow


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

like image 26
android developer Avatar answered Oct 05 '22 21:10

android developer


Parcelable is mainly related to IPC using the Binder infrastructure, where data is passed as Parcels.

Since Android relies a lot on Binder for most, if not all, IPC tasks, it makes sense to implement Parcelable in most places, and especially in the framework, because it allows pass an object to another process if you need that. It makes objects "transportable".

But if you have a non Android-specific business layer which extensively use serializables to save object states, and only need to store them to the file system, then I think that serializable is fine. It allows to avoid the Parcelable boiler-plate code.

like image 28
olivierg Avatar answered Oct 05 '22 20:10

olivierg


Based on this article http://www.mooproductions.org/node/6?page=5 Parcelable should be faster.

Not mentioned in the article, is that I don't htink that serializable objects will work in AIDL for remote services.

like image 31
Mike dg Avatar answered Oct 05 '22 21:10

Mike dg


I just use GSON -> Serialise to JSON String -> Restore Object from JSON String.

like image 40
F.O.O Avatar answered Oct 05 '22 21:10

F.O.O