Преимущество использования Parcelable вместо сериализации объекта - PullRequest
97 голосов
/ 05 апреля 2011

Как я понимаю, Bundle и Parcelable относятся к тому, как Android выполняет сериализацию. Он используется, например, при передаче данных между действиями. Но мне интересно, есть ли какие-либо преимущества в использовании Parcelable вместо классической сериализации в случае сохранения состояния моих бизнес-объектов, например, во внутренней памяти? Будет ли это проще или быстрее классического способа? Где я должен использовать классическую сериализацию и где лучше использовать связки?

Ответы [ 9 ]

100 голосов
/ 05 апреля 2011

Из "Pro Android 2"

ПРИМЕЧАНИЕ. Видение Parcelable могло вызвать вопрос, почему Android не использует встроенный механизм сериализации Java?Оказывается, команда Android пришла к выводу, что сериализация в Java слишком медленная, чтобы удовлетворить требования Android к межпроцессному взаимодействию.Поэтому команда создала решение Parcelable.Подход Parcelable требует явной сериализации членов вашего класса, но в итоге вы получаете намного более быструю сериализацию ваших объектов.

Также следует понимать, что Android предоставляет два механизма, которые позволяют передавать данные другому процессу.Первый - передать пакет в действие с помощью намерения, а второй - передать Parcelable в службу.Эти два механизма не являются взаимозаменяемыми и их не следует путать.То есть Parcelable не предназначен для передачи в действие.Если вы хотите начать действие и передать ему некоторые данные, используйте пакет.Parcelable предназначен для использования только как часть определения AIDL.

22 голосов
/ 10 апреля 2011

Serializable комично медленно на Android. Граница бесполезна во многих случаях на самом деле.

Parcel и Parcelable фантастически быстрые, но в документации говорится, что вы не должны использовать их для сериализации общего назначения в хранилище, поскольку реализация зависит от версии Android (например, ОС). обновление может сломать приложение, на которое оно опирается).

Лучшее решение проблемы сериализации данных в хранилище с разумной скоростью - это выполнить свою собственную. Я лично использую один из моих собственных служебных классов, интерфейс которого похож на Parcel и который может очень эффективно сериализовать все стандартные типы (за счет безопасности типов). Вот сокращенная версия этого:

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

}
11 голосов
/ 28 августа 2015

Посмотрите, как быстро Parcelable чем Serializable.


enter image description here

с ПОЧЕМУ МЫ ЛЮБИМ СВОБОДНО


enter image description here

от Parcelable против Serializable

10 голосов
/ 08 февраля 2012

Если вам нужна сериализация для хранения, но вы хотите избежать потери скорости отражения, вызванной интерфейсом Serializable , вы должны явно создать свой собственный протокол сериализации с интерфейсом Externalizable .

При правильной реализации это соответствует скорости Parcelable, а также учитывает совместимость между различными версиями Android и / или платформы Java.

Эта статья также может прояснить ситуацию:

В чем разница между Serializable и Externalizable в Java?

В sidenote это также самый быстрый метод сериализации во многих тестах, опережающий Kryo, Avro, Protocol Buffers и Jackson(json):

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

7 голосов
/ 26 февраля 2014

Кажется, что в настоящее время разница не так заметна, по крайней мере, когда вы запускаете ее между своими действиями.

Согласно тестам, показанным на на этом сайте , Parcelable составляет околоВ 10 раз быстрее на новейших устройствах (например, Nexus 10) и примерно на 17 быстрее на старых (например, Желание Z) * ​​1005 *

, поэтому вам решать, стоит ли оно того.

возможнодля относительно небольших и простых классов Serializable - это хорошо, а для остальных вы должны использовать Parcelable

4 голосов
/ 08 апреля 2011

Parcelable в основном связан с IPC, использующим инфраструктуру Binder , где данные передаются как Parcels .

Поскольку Android в большинстве случаев полагается на Binder, еслиНе все, задачи IPC, имеет смысл реализовать Parcelable в большинстве мест, и особенно в рамках, потому что он позволяет передавать объект другому процессу, если вам это нужно.Это делает объекты «переносимыми».

Но если у вас есть бизнес-уровень, не относящийся к Android, который широко использует сериализуемые для сохранения состояний объектов, и нужно только сохранять их в файловой системе, то я думаю, что сериализуемыйхорошо.Это позволяет избежать кода Parcelable кодовой пластины.

1 голос
/ 10 сентября 2016

Я просто использую GSON -> Serialise to JSON String -> Восстановить объект из JSON String.

1 голос
/ 05 апреля 2011

На основании этой статьи http://www.mooproductions.org/node/6?page=5 Parcelable должен быть быстрее.

В статье не упоминается, что я не думаю, что сериализуемые объекты будут работать в AIDL для удаленных служб.

0 голосов
/ 11 апреля 2017

Кроме того, Parcelable предлагает пользовательскую реализацию, в которой пользователь получает возможность разбирать каждый из своих объектов, переопределяя writeToParcel (). Однако сериализация не делает эту пользовательскую реализацию, поскольку ее способ передачи данных использует API-интерфейс JAVA-отражения.

...