안드로이드 : Parcelable과 Serializable의 차이점은 무엇입니까? 위해 2 개의 인터페이스를 제공하는 이유는

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");

결론

  1. ParcelableSerializable인터페이스 보다 빠릅니다
  2. Parcelable인터페이스에 비해 구현하는 데 더 많은 시간이 소요 Serializable인터페이스
  3. Serializable 인터페이스는 구현하기 쉽다
  4. Serializable 인터페이스는 많은 임시 객체를 생성하고 많은 가비지 수집을 유발합니다.
  5. 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 = ""
}

참고로 두 개 이상의 주석이다 transientoptional. 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)
    }

에 대한


답변

좋은 시민이 되려면 Parcelable을 구현하는 데 여분의 시간이 걸리며 10 배 더 빠르게 수행하고 더 적은 리소스를 사용합니다.

그러나 대부분의 경우 Serializable의 느림은 눈에 띄지 않습니다. 자유롭게 사용하되 직렬화는 비용이 많이 드는 작업이므로 최소한으로 유지하십시오.

수천 개의 직렬화 된 객체가있는 목록을 전달하려는 경우 전체 프로세스가 1 초 이상 걸릴 수 있습니다. 세로에서 자연 환경으로의 전환 또는 회전이 매우 느리게 느껴질 수 있습니다.

이 시점의 출처 : http://www.developerphil.com/parcelable-vs-serializable/


답변

Parcelable에서 개발자는 마샬링 및 마샬링 해제를위한 사용자 지정 코드를 작성하므로 직렬화에 비해 가비지 개체가 줄어 듭니다. 이 사용자 정의 구현으로 인해 직렬화를 통한 Parcelable의 성능이 크게 향상됩니다 (약 2 배 더 빠름).

Serializable은 마커 인터페이스로, 사용자가 요구 사항에 따라 데이터를 마샬링 할 수 없음을 나타냅니다. 직렬화에서 마샬링 작업은 Java Reflection API를 사용하여 JVM (Java Virtual Machine)에서 수행됩니다. 이는 Java 객체의 멤버와 동작을 식별하는 데 도움이되지만 많은 가비지 객체를 생성하게됩니다.이로 인해 직렬화 프로세스는 Parcelable에 비해 느립니다.

편집하다: 마샬링과 비 정렬 화의 의미는 무엇입니까?

간단히 말해서 “마샬링”은 데이터 또는 객체를 바이트 스트림으로 변환하는 프로세스를 말하며 “비 정렬 화”는 바이트 스트림 베크를 원래 데이터 또는 객체로 변환하는 역 프로세스입니다. 변환은 “직렬화”를 통해 달성됩니다.

http://www.jguru.com/faq/view.jsp?EID=560072


답변

나는 실제로 Serializable을 옹호하는 한 사람이 될 것입니다. 몇 년 전보다 장치가 훨씬 우수하고 다른 미묘한 차이가 있기 때문에 속도 차이는 더 이상 급격하지 않습니다. 자세한 내용 은 문제에 대한 내 블로그 게시물을 참조하십시오 .


답변

Parcelable은 Android 개발에서 일종의 표준입니다. 그러나 속도 때문에

데이터 전송에는 소포를 사용하는 것이 좋습니다. 그러나이 저장소에 표시된 것처럼 직렬화 가능을 올바르게 사용하면 하면 직렬화가 때로는 소포 가능보다 훨씬 빠르다는 것을 알 수 있습니다. 또는 적어도 타이밍이 비슷합니다.

Parcelable이 Serializable보다 빠릅니까?

일반적인 Android 장치 (정상적으로 수행 된 경우 *)의 일반적인 Java 직렬화는 Parcelable보다 쓰기의 경우 약 3.6 배, 읽기의 경우 약 1.6 배 더 빠릅니다. 또한 Java Serialization (올바르게 수행 된 경우)이 빠른 저장 메커니즘이며 각각 10 개의 필드가있는 11000 개의 객체로 구성된 비교적 큰 객체 그래프에서도 수용 가능한 결과를 제공합니다.

일반적으로 맹목적으로 “소포가 더 빠르다”고 맹목적으로 언급 한 모든 사람들은 기본적으로 자동 직렬화와 비교하여 내부에서 많은 반사를 사용합니다. Parcelable은 스트림에 데이터를 쓰는 수동 (매우 복잡한) 절차를 사용하기 때문에 불공평 한 비교입니다. 일반적으로 언급되지 않은 것은 문서에 따라 표준 Java Serializable이 writeObject () 및 readObject () 메소드를 사용하여 수동으로 수행 될 수 있다는 것입니다. 자세한 정보는 JavaDocs를 참조하십시오. 이것이 최상의 성능을 위해 수행되어야하는 방법입니다.

따라서 serializable이 더 빠르고 구현하기 쉽다면 왜 안드로이드가 소포를 가질 수 있습니까?

이유는 기본 코드입니다. 소포 가능 프로세스 간 통신을 위해 만들어지지 않습니다. 인터 코드 통신 에도 사용할 수 있습니다 . C ++ 기본 레이어에서 개체를 보내고받을 수 있습니다. 그게 다야.

무엇을 선택해야합니까? 둘 다 잘 작동합니다. 그러나 Parcelable은 Google에서 권장하기 때문에 더 나은 선택이라고 생각합니다.이 스레드에서 볼 수 있듯이 훨씬 감사합니다.