내가 이해 Bundle
하고 Parcelable
Android가 직렬화를 수행하는 방식에 속합니다. 예를 들어 활동간에 데이터를 전달하는 데 사용됩니다. 하지만 Parcelable
예를 들어 비즈니스 개체의 상태를 내부 메모리에 저장하는 경우 클래식 직렬화 대신 사용하면 어떤 이점이 있는지 궁금합니다 . 고전적인 방법보다 더 간단하거나 빠를까요? 클래식 직렬화를 사용해야하는 곳과 번들을 사용하는 것이 더 좋은 곳은 어디입니까?
내가 이해 Bundle
하고 Parcelable
Android가 직렬화를 수행하는 방식에 속합니다. 예를 들어 활동간에 데이터를 전달하는 데 사용됩니다. 하지만 Parcelable
예를 들어 비즈니스 개체의 상태를 내부 메모리에 저장하는 경우 클래식 직렬화 대신 사용하면 어떤 이점이 있는지 궁금합니다 . 고전적인 방법보다 더 간단하거나 빠를까요? 클래식 직렬화를 사용해야하는 곳과 번들을 사용하는 것이 더 좋은 곳은 어디입니까?
답변:
"Pro Android 2"에서
참고 : Parcelable을 보면 Android가 내장 된 Java 직렬화 메커니즘을 사용하지 않는 이유는 무엇입니까? Android 팀은 Java의 직렬화가 Android의 프로세스 간 통신 요구 사항을 충족하기에는 너무 느리다는 결론에 도달했습니다. 그래서 팀은 Parcelable 솔루션을 구축했습니다. Parcelable 접근 방식을 사용하려면 클래스의 멤버를 명시 적으로 직렬화해야하지만 결국 객체의 직렬화가 훨씬 빨라집니다.
또한 Android는 데이터를 다른 프로세스로 전달할 수있는 두 가지 메커니즘을 제공합니다. 첫 번째는 인 텐트를 사용하여 활동에 번들을 전달하는 것이고, 두 번째는 서비스에 Parcelable을 전달하는 것입니다. 이 두 메커니즘은 상호 교환 할 수 없으며 혼동해서는 안됩니다. 즉, Parcelable은 활동에 전달되지 않습니다. 활동을 시작하고 일부 데이터를 전달하려면 번들을 사용하십시오. Parcelable은 AIDL 정의의 일부로 만 사용됩니다.
getBundle
메소드를 생성 한 다음 writeToParcel
as 에서 호출 dest.writeBundle(getBundle());
하면 객체에서 자동으로 두 옵션을 사용할 수 있습니다. 라이브 객체가 주목 대한 흥미 소포 특징이 있습니다 developer.android.com/reference/android/os/Parcel.html
Serializable
Android에서는 우스꽝스럽게 느립니다. 실제로 많은 경우에 쓸모없는 경계선.
Parcel
그리고 Parcelable
놀랍도록 빠르지 만, 그 문서 는 안드로이드의 다른 버전에 따라 구현이 다르기 때문에 스토리지에 대한 범용 직렬화에 사용해서는 안된다고 말합니다.
합리적인 속도로 데이터를 스토리지에 직렬화하는 문제에 대한 최상의 솔루션은 직접 롤링하는 것입니다. 나는 개인적으로 유사한 인터페이스를 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++;
}
}
}
즉, 저장 목적으로 직렬화가 필요하지만 직렬화 가능 인터페이스로 인한 반사 속도 저하를 방지 하려면 Externalizable 인터페이스를 사용하여 고유 한 직렬화 프로토콜을 명시 적으로 만들어야합니다 .
제대로 구현되면 Parcelable의 속도와 일치하며 Android 및 / 또는 Java 플랫폼의 여러 버전 간의 호환성을 고려합니다.
이 기사는 다음과 같은 사항을 정리할 수도 있습니다.
Java에서 직렬화 가능과 외부화 가능의 차이점은 무엇입니까?
참고로 Kryo, Avro, Protocol Buffers 및 Jackson (json)을 제치고 많은 벤치 마크에서 가장 빠른 직렬화 기술이기도합니다.
http://code.google.com/p/thrift-protobuf-compare/wiki/Benchmarking
요즘에는 그 차이가 그다지 눈에 띄지 않는 것 같습니다. 적어도 자신의 활동 사이에서 실행할 때는 아닙니다.
이 웹 사이트 에 표시된 테스트에 따르면 Parcelable은 최신 기기 (예 : 넥서스 10)에서 약 10 배, 오래된 기기 (예 : desire Z)에서는 약 17 배 더 빠릅니다.
그래서 그만한 가치가 있는지 결정하는 것은 당신에게 달려 있습니다.
비교적 작고 단순한 클래스의 경우 Serializable이 괜찮고 나머지는 Parcelable을 사용해야합니다.
Parcelable 주로 사용 IPC 관련된 바인더 데이터로 전달 인프라 소포 .
Android는 전부는 아니지만 대부분의 IPC 작업에 Binder를 많이 사용하므로 필요한 경우 객체를 다른 프로세스로 전달할 수 있으므로 대부분의 위치, 특히 프레임 워크에서 Parcelable을 구현하는 것이 좋습니다. 그것은 개체를 "이동 가능"하게 만듭니다.
그러나 직렬화 가능을 광범위하게 사용하여 객체 상태를 저장하고 파일 시스템에 저장하기 만하면되는 비 Android 관련 비즈니스 계층이 있다면 직렬화 가능이 괜찮다고 생각합니다. Parcelable 상용구 코드를 피할 수 있습니다.
이 기사를 기반으로 http://www.mooproductions.org/node/6?page=5 Parcelable이 더 빠를 것입니다.
기사에서 언급하지 않은 것은 직렬화 가능한 객체가 원격 서비스를 위해 AIDL에서 작동 할 것이라고 생각하지 않는다는 것입니다.
GSON-> Serialise to JSON String-> Restore Object from JSON String을 사용합니다.