Programming

객체 직렬화 대신 Parcelable 사용의 이점

procodes 2020. 8. 23. 10:08
반응형

객체 직렬화 대신 Parcelable 사용의 이점


내가 이해 Bundle하고 ParcelableAndroid가 직렬화를 수행하는 방식에 속합니다. 예를 들어 활동간에 데이터를 전달하는 데 사용됩니다. 하지만 Parcelable예를 들어 비즈니스 개체의 상태를 내부 메모리에 저장하는 경우 클래식 직렬화 대신 사용하면 어떤 이점이 있는지 궁금합니다 . 고전적인 방법보다 더 간단하거나 빠를까요? 클래식 직렬화를 사용해야하는 곳과 번들을 사용하는 것이 더 좋은 곳은 어디입니까?


"Pro Android 2"에서

참고 : Parcelable을 보면 Android가 내장 된 Java 직렬화 메커니즘을 사용하지 않는 이유는 무엇입니까? Android 팀은 Java의 직렬화가 Android의 프로세스 간 통신 요구 사항을 충족하기에는 너무 느리다는 결론에 도달했습니다. 그래서 팀은 Parcelable 솔루션을 구축했습니다. Parcelable 접근 방식을 사용하려면 클래스의 멤버를 명시 적으로 직렬화해야하지만 결국 객체의 직렬화가 훨씬 빨라집니다.

또한 Android는 데이터를 다른 프로세스로 전달할 수있는 두 가지 메커니즘을 제공합니다. 첫 번째는 인 텐트를 사용하여 활동에 번들을 전달하는 것이고, 두 번째는 서비스에 Parcelable을 전달하는 것입니다. 이 두 메커니즘은 상호 교환 할 수 없으며 혼동해서는 안됩니다. 즉, Parcelable은 활동에 전달되지 않습니다. 활동을 시작하고 일부 데이터를 전달하려면 번들을 사용하십시오. Parcelable은 AIDL 정의의 일부로 만 사용됩니다.


SerializableAndroid에서는 우스꽝스럽게 느립니다. 실제로 많은 경우에 쓸모없는 경계선.

Parcel그리고 Parcelable놀랍도록 빠르지 만, 그 문서 는 안드로이드의 다른 버전에 따라 구현이 다르기 때문에 스토리지에 대한 범용 직렬화에 이것을 사용해서는 안된다고 말합니다 (즉, OS 업데이트는 그것에 의존하는 앱을 망가뜨릴 수 있습니다).

합리적인 속도로 데이터를 스토리지에 직렬화하는 문제에 대한 최상의 솔루션은 직접 롤링하는 것입니다. 나는 개인적으로 유사한 인터페이스를 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++;
        }
    }

}

Parcelable 이 Serializable보다 얼마나 빠른지 확인 하세요 .


enter image description here

우리가 PARCELABLE을 사랑하는 이유 에서


enter image description here

에서 Parcelable 직렬화 대


즉, 저장 목적으로 직렬화가 필요하지만 직렬화 가능 인터페이스 에 의해 발생하는 반사 속도 저하를 피 하려면 Externalizable 인터페이스를 사용하여 고유 한 직렬화 프로토콜을 명시 적으로 만들어야합니다 .

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


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


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.


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.


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


Also Parcelable offers custom implementation where the user gets an chance to parcel each of his objects by overriding the writeToParcel(), However serialization does not this custom implementation as its way of passing data involves JAVA reflection API.

참고URL : https://stackoverflow.com/questions/5550670/benefit-of-using-parcelable-instead-of-serializing-object

반응형