Android가 객체 직렬화를 위해 2 개의 인터페이스를 제공하는 이유는 무엇입니까? 직렬화 가능 객체가 Android와 상호 작용Binder
및 AIDL 파일과 상호 작용합니까?
Android가 객체 직렬화를 위해 2 개의 인터페이스를 제공하는 이유는 무엇입니까? 직렬화 가능 객체가 Android와 상호 작용Binder
및 AIDL 파일과 상호 작용합니까?
답변:
안드로이드에서는 객체를 액티비티에 전달할 수 없습니다. 이렇게하려면 개체가 구현 Serializable
또는 Parcelable
인터페이스 중 하나 여야합니다 .
직렬화 가능
Serializable
표준 Java 인터페이스입니다. Serializable
인터페이스를 구현 하고 재정의 메소드를 추가 할 수 있습니다 . 이 접근법의 문제점은 리플렉션이 사용되며 느리게 진행된다는 것입니다. 이 메소드는 많은 임시 오브젝트를 작성하고 상당히 많은 가비지 콜렉션을 발생시킵니다. 하나,Serializable
인터페이스는 구현하기가 더 쉽습니다.
아래 예제 (Serializable)를보십시오.
// MyObjects Serializable class
import java.io.Serializable;
import java.util.ArrayList;
import java.util.TreeMap;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Serializable {
private String name;
private int age;
public ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
super();
this.name = name;
this.age = age;
this.address = address;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyObjects instance via intent
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getSerializableExtra("UniqueKey");
소포
Parcelable
프로세스가보다 빠릅니다 Serializable
. 그 이유 중 하나는 리플렉션을 사용하여 추론하는 대신 직렬화 프로세스를 명시하고 있기 때문입니다. 또한이 목적을 위해 코드가 크게 최적화 된 이유도 있습니다.
아래 예 (Parcelable)를보십시오.
// MyObjects Parcelable class
import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
public class MyObjects implements Parcelable {
private int age;
private String name;
private ArrayList<String> address;
public MyObjects(String name, int age, ArrayList<String> address) {
this.name = name;
this.age = age;
this.address = address;
}
public MyObjects(Parcel source) {
age = source.readInt();
name = source.readString();
address = source.createStringArrayList();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(age);
dest.writeString(name);
dest.writeStringList(address);
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public ArrayList<String> getAddress() {
if (!(address == null))
return address;
else
return new ArrayList<String>();
}
public static final Creator<MyObjects> CREATOR = new Creator<MyObjects>() {
@Override
public MyObjects[] newArray(int size) {
return new MyObjects[size];
}
@Override
public MyObjects createFromParcel(Parcel source) {
return new MyObjects(source);
}
};
}
// MyObjects instance
MyObjects mObjects = new MyObjects("name", "age", "Address array here");
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putExtra("UniqueKey", mObjects);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
MyObjects workorder = (MyObjects) mIntent.getParcelableExtra("UniqueKey");
ArrayList
다음과 같이 Parcelable 객체를 전달할 수 있습니다 .
// Array of MyObjects
ArrayList<MyObjects> mUsers;
// Passing MyOjects instance
Intent mIntent = new Intent(FromActivity.this, ToActivity.class);
mIntent.putParcelableArrayListExtra("UniqueKey", mUsers);
startActivity(mIntent);
// Getting MyObjects instance
Intent mIntent = getIntent();
ArrayList<MyObjects> mUsers = mIntent.getParcelableArrayList("UniqueKey");
결론
Parcelable
Serializable
인터페이스 보다 빠릅니다Parcelable
인터페이스에 비해 구현하는 데 더 많은 시간이 소요 Serializable
인터페이스Serializable
인터페이스는 구현하기 쉽다 Serializable
인터페이스는 많은 임시 객체를 생성하고 많은 가비지 수집을 유발합니다.Parcelable
안드로이드에서 인 텐트를 통해 배열을 전달할 수 있습니다.직렬화 가능 은 표준 Java 인터페이스입니다. 인터페이스를 구현하여 Serializable 클래스를 표시하면 Java는 특정 상황에서 자동으로 직렬화합니다.
소포 은 직렬화를 직접 구현하는 Android 전용 인터페이스입니다. Serializable보다 훨씬 효율적이고 기본 Java 직렬화 체계의 일부 문제를 해결하기 위해 작성되었습니다.
바인더와 AIDL이 Parcelable 객체와 함께 작동한다고 생각합니다.
그러나 Intents에서 Serializable 객체를 사용할 수 있습니다.
Parcelable 대 직렬화 이 두 가지를 참조하십시오.
자바와 코 틀린
1) 자바
직렬화 가능, 단순성
직렬화가 무엇입니까?
직렬화 가능은 표준 Java 인터페이스입니다. Android SDK의 일부가 아닙니다. 단순함은 아름다움입니다. 이 인터페이스를 구현하면 POJO가 한 활동에서 다른 활동으로 이동할 준비가됩니다.
public class TestModel implements Serializable {
String name;
public TestModel(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Serializable의 장점은 클래스와 그 자식에 Serializable 인터페이스 만 구현하면된다는 것입니다. 마커 인터페이스입니다. 즉, 구현할 메소드가 없으며 Java는 효율적으로 직렬화하기 위해 최선을 다할 것입니다.
이 접근법의 문제점은 리플렉션이 사용되며 느리게 진행된다는 것입니다. 이 메커니즘은 또한 많은 임시 객체를 생성하고 많은 가비지 수집을 유발하는 경향이 있습니다.
소포, 속도
소포는 무엇입니까?
Parcelable은 또 다른 인터페이스입니다. 경쟁사 (당신이 잊어 버린 경우 직렬화 가능)에도 불구하고 Android SDK의 일부입니다. 이제 Parcelable은 사용할 때 반사가없는 방식으로 특별히 설계되었습니다. 우리는 직렬화 프로세스에 대해 실제로 명시 적이기 때문입니다.
public class TestModel implements Parcelable {
String name;
public TestModel(String name, String id) {
this.name = name;
}
protected TestModel(Parcel in) {
this.name = in.readString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
}
public static final Parcelable.Creator<TestModel> CREATOR = new Parcelable.Creator<TestModel>() {
@Override
public TestModel createFromParcel(Parcel source) {
return new TestModel(source);
}
@Override
public TestModel[] newArray(int size) {
return new TestModel[size];
}
};
}
이제 승자는
Philippe Breault가 수행 한 테스트 결과에 따르면 Parcelable은 Serializable보다 10 배 이상 빠릅니다. 다른 Google 엔지니어들도이 진술을지지합니다.
그들에 따르면 기본 Serializable 접근 방식은 Parcelable보다 느립니다. 그리고 우리는 두 당사자 사이에 합의를 맺었습니다! 그러나이 두 가지를 전혀 비교하는 것은 불공평합니다! Parcelable을 사용하면 실제로 사용자 정의 코드를 작성하기 때문입니다. 해당 POJO를 위해 특별히 작성된 코드입니다. 따라서 가비지가 생성되지 않으며 결과가 더 좋습니다. 그러나 기본 직렬화 가능 방식에서는 Java의 자동 직렬화 프로세스를 사용합니다. 이 프로세스는 분명히 사용자 정의가 아니며 많은 쓰레기를 만듭니다! 따라서 더 나쁜 결과.
Stop Stop !!!!, 결정하기 전에
이제 또 다른 접근법이 있습니다. Serializable 뒤에있는 전체 자동 프로세스는 writeObject () 및 readObject () 메소드를 사용하는 사용자 정의 코드로 대체 될 수 있습니다. 이러한 방법은 구체적입니다. 사용자 지정 직렬화 동작과 함께 직렬화 가능 접근 방식을 사용하려면 아래 두 가지와 동일한 서명을 가진이 두 가지 방법을 포함해야합니다.
private void writeObject(java.io.ObjectOutputStream out)
throws IOException;
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException;
private void readObjectNoData()
throws ObjectStreamException;
그리고 Parcelable과 Custom Serializable의 비교는 공정한 것 같습니다! 결과는 놀랍습니다! 맞춤형 Serializable 접근 방식은 Parcelable보다 쓰기 속도가 3 배 이상 빨라지고 읽기 속도가 1.6 배 빠릅니다.
편집 : -----
2) Kotlinx 직렬화
코 틀린 스 직렬화 라이브러리
For Kotlin serialization need to add below dependency and plugin
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
apply plugin: 'kotlinx-serialization'
귀하의 build.gradle
파일
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.example.smile.kotlinxretrosample"
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.9.1"
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
implementation 'com.android.support:design:28.0.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
직렬화 는 매우 쉽게 수행 @Serializable
됩니다. 아래와 같이 주석으로 의도 된 클래스에 주석을 달아야합니다.
import kotlinx.serialization.Serializable
@Serializable
class Field {
var count: Int = 0
var name: String = ""
}
참고로 두 개 이상의 주석이다 transient
와 optional
. Transient를 사용하면 시리얼 라이저가 해당 필드를 무시하게되며, 옵션을 사용하면 필드가 누락 된 경우 시리얼 라이저가 중단되지 않지만 동시에 기본값을 제공해야합니다.
@Optional
var isOptional: Boolean = false
@Transient
var isTransient: Boolean = false
참고 : 이것은 데이터 클래스에서도 작동 할 수 있습니다.
실제로 이것을 실제로 사용하려면 JSON을 객체로 변환하고 다시 변환하는 방법의 예를 들어 보겠습니다.
fun toObject(stringValue: String): Field {
return JSON.parse(Field.serializer(), stringValue)
}
fun toJson(field: Field): String {
//Notice we call a serializer method which is autogenerated from our class
//once we have added the annotation to it
return JSON.stringify(Field.serializer(), field)
}
에 대한 더
Serialization
.
좋은 시민이 되려면 Parcelable을 구현하는 데 여분의 시간이 걸리며 10 배 더 빠르게 수행하고 더 적은 리소스를 사용합니다.
그러나 대부분의 경우 Serializable의 느림은 눈에 띄지 않습니다. 자유롭게 사용하되 직렬화는 비용이 많이 드는 작업이므로 최소한으로 유지하십시오.
수천 개의 직렬화 된 객체가있는 목록을 전달하려는 경우 전체 프로세스가 1 초 이상 걸릴 수 있습니다. 세로에서 자연 환경으로의 전환 또는 회전이 매우 느리게 느껴질 수 있습니다.
이 시점의 출처 : http://www.developerphil.com/parcelable-vs-serializable/
Parcelable에서 개발자는 마샬링 및 마샬링 해제를위한 사용자 지정 코드를 작성하므로 직렬화에 비해 가비지 개체가 줄어 듭니다. 이 사용자 정의 구현으로 인해 직렬화를 통한 Parcelable의 성능이 크게 향상됩니다 (약 2 배 더 빠름).
Serializable은 마커 인터페이스로, 사용자가 요구 사항에 따라 데이터를 마샬링 할 수 없음을 나타냅니다. 직렬화에서 마샬링 작업은 Java Reflection API를 사용하여 JVM (Java Virtual Machine)에서 수행됩니다. 이는 Java 객체의 멤버와 동작을 식별하는 데 도움이되지만 많은 가비지 객체를 생성하게됩니다.이로 인해 직렬화 프로세스는 Parcelable에 비해 느립니다.
편집하다: 마샬링과 비 정렬 화의 의미는 무엇입니까?
간단히 말해서 "마샬링"은 데이터 또는 객체를 바이트 스트림으로 변환하는 프로세스를 말하며 "비 정렬 화"는 바이트 스트림 베크를 원래 데이터 또는 객체로 변환하는 역 프로세스입니다. 변환은 "직렬화"를 통해 달성됩니다.
나는 실제로 Serializable을 옹호하는 한 사람이 될 것입니다. 몇 년 전보다 장치가 훨씬 우수하고 다른 미묘한 차이가 있기 때문에 속도 차이는 더 이상 급격하지 않습니다. 자세한 내용 은 문제에 대한 내 블로그 게시물을 참조하십시오 .
데이터 전송에는 소포를 사용하는 것이 좋습니다. 그러나이 저장소에 표시된 것처럼 직렬화 가능을 올바르게 사용하면 하면 직렬화가 때로는 소포 가능보다 훨씬 빠르다는 것을 알 수 있습니다. 또는 적어도 타이밍이 비슷합니다.
일반적인 Android 장치 (정상적으로 수행 된 경우 *)의 일반적인 Java 직렬화는 Parcelable보다 쓰기의 경우 약 3.6 배, 읽기의 경우 약 1.6 배 더 빠릅니다. 또한 Java Serialization (올바르게 수행 된 경우)이 빠른 저장 메커니즘이며 각각 10 개의 필드가있는 11000 개의 객체로 구성된 비교적 큰 객체 그래프에서도 수용 가능한 결과를 제공합니다.
일반적으로 맹목적으로 "소포가 더 빠르다"고 맹목적으로 언급 한 모든 사람들은 기본적으로 자동 직렬화와 비교하여 내부에서 많은 반사를 사용합니다. Parcelable은 스트림에 데이터를 쓰는 수동 (매우 복잡한) 절차를 사용하기 때문에 불공평 한 비교입니다. 일반적으로 언급되지 않은 것은 문서에 따라 표준 Java Serializable이 writeObject () 및 readObject () 메소드를 사용하여 수동으로 수행 될 수 있다는 것입니다. 자세한 정보는 JavaDocs를 참조하십시오. 이것이 최상의 성능을 위해 수행되어야하는 방법입니다.
이유는 기본 코드입니다. 소포 가능 프로세스 간 통신을 위해 만들어지지 않습니다. 인터 코드 통신 에도 사용할 수 있습니다 . C ++ 기본 레이어에서 개체를 보내고받을 수 있습니다. 그게 다야.
무엇을 선택해야합니까? 둘 다 잘 작동합니다. 그러나 Parcelable은 Google에서 권장하기 때문에 더 나은 선택이라고 생각합니다.이 스레드에서 볼 수 있듯이 훨씬 감사합니다.
@보다 참조 http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@보다 참조 http://developer.android.com/reference/android/os/Parcelable.html
Serializable은 표준 Java 인터페이스이고 Parcelable은 Android 개발 용입니다.
마샬링 및 마샬링 해제와 관련된 성능 문제가 있습니다. Parcelable은 Serializable보다 두 배 빠릅니다.
다음 링크를 통해 이동하십시오 :
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
Serializable 인터페이스는 Parcelable 인터페이스와 같은 방식으로 사용될 수 있으므로 성능이 훨씬 향상됩니다. 수동 마샬링 및 비 정렬 화 프로세스를 처리하기 위해이 두 가지 방법을 덮어 쓰십시오.
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
여전히 네이티브 Android를 개발할 때 Android API를 사용하는 것이 좋습니다.
보다 :
답변이 늦었지만 다른 사람들에게 도움이되기를 바랍니다.
속도 측면 에서 Parcelable > Serializable
. 그러나 Custom Serializable 은 예외입니다. 그것은 거의 Parcelable의 범위에 있거나 더 빠릅니다.
참조 : https://www.geeksforgeeks.org/customized-serialization-and-deserialization-in-java/
예 :
직렬화 할 사용자 정의 클래스
class MySerialized implements Serializable {
String deviceAddress = "MyAndroid-04";
transient String token = "AABCDS"; // sensitive information which I do not want to serialize
private void writeObject(ObjectOutputStream oos) throws Exception {
oos.defaultWriteObject();
oos.writeObject("111111" + token); // Encrypted token to be serialized
}
private void readObject(ObjectInputStream ois) throws Exception {
ois.defaultReadObject();
token = ((String) ois.readObject()).subString(6); // Decrypting token
}
}
직렬화는 반사를 사용하고 많은 GC를 유발하기 때문에 바인더로 직렬화하는 것보다 훨씬 빠르게 소포 가능합니다. Parcelable은 객체를 전달하도록 최적화 된 디자인입니다.
여기에 참조 링크가 있습니다. http://www.developerphil.com/parcelable-vs-serializable/
직렬화 가능
직렬화는 현저한 인터페이스이거나 빈 인터페이스로 호출 할 수 있습니다. 사전 구현 된 메소드가 없습니다. 직렬화 가능은 객체를 바이트 스트림으로 변환합니다. 따라서 사용자는 한 활동간에 데이터를 다른 활동으로 전달할 수 있습니다. 직렬화 가능의 주요 장점은 데이터 작성 및 전달이 매우 쉽지만 소포 가능 처리에 비해 느린 프로세스입니다.
소포
소포 가능은 직렬화 가능보다 빠릅니다. Parcel은 객체를 바이트 스트림으로 변환하고 두 활동 사이에 데이터를 전달합니다. 소포 가능 코드 작성은 직렬화에 비해 약간 복잡합니다. 두 활동 사이에 데이터를 전달하는 동안 더 많은 임시 오브젝트를 작성하지 않습니다.