Преимущество использования Parcelable вместо сериализации объекта

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

Ответ 1

От "Pro Android 2"

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

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

Ответ 2

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

}

Ответ 4

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

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

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

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

В боковом объявлении он также является самым быстрым методом сериализации во многих тестах, избивая Kryo, Avro, Protocol Buffers и Jackson (json):

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

Ответ 5

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

В соответствии с тестами, показанными на этом веб-сайте, Parcelable примерно на 10 раз быстрее на новейших устройствах (например, nexus 10) и примерно на 17 быстрее на старых (например, желание Z)

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

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