Android: різниця між розбірливим і серіалізаційним?


313

Чому Android надає 2 інтерфейси для серіалізації об’єктів? Чи взаємодіють об'єкти серіалізації з файлами Android Binderта AIDL?

Відповіді:


444

В Android ми не можемо просто передавати об’єкти діяльності. Для цього об'єкти повинні або реалізувати, Serializableабо Parcelableінтерфейс.

Серіалізація

Serializableє стандартним інтерфейсом Java. Ви можете просто реалізувати 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. Parcelableшвидше Serializableінтерфейсу
  2. ParcelableІнтерфейс займає більше часу на реалізацію порівняно з Serializableінтерфейсом
  3. Serializable інтерфейс простіший в реалізації
  4. Serializable інтерфейс створює безліч тимчасових об'єктів і спричиняє досить багато сміття
  5. Parcelable масив може бути переданий за допомогою Intent в android

2
@Sujith, що ти маєш на увазі під рефлексією ? Що таке рефлексія ?
AnV

11
@AbhinavVutukuri Reflection - термін для огляду об'єктів, полів та методів під час виконання за допомогою Object.getClass () тощо.
FaultException

2
Серіалізалізація краще зберігати дані, об'єкти, що розширюються, з іншого боку, взагалі не повинні зберігатися. Це дійсно погана практика
TheAnimatrix

2
@Sujith Як заявляла більше однієї людини, об'єкти, що розширюються, не можуть зберігатися (надійно), але серіалізаційні об'єкти можуть (в межах). Оскільки ваша відповідь набрала найбільшу оцінку та створює враження, що вона охоплює всі важливі відмінності, вам, мабуть, слід згадати цей момент.
LarsH

4
Тепер реалізація Parcelable така ж швидка, як і Serializable, просто натисніть ALT + INSERT на будь-якому класі, що реалізує Parcelable в Android Studio, і IDE зробить це.
Алі Нем

183

Serializable - це стандартний інтерфейс Java. Ви просто позначите клас Serializable, реалізуючи інтерфейс, і Java автоматично серіалізує його в певних ситуаціях.

Parcelable - це специфічний для Android інтерфейс, де ви реалізуєте серіалізацію самостійно. Він був створений для того, щоб бути набагато ефективнішим, ніж серіалізація, і щоб обійти деякі проблеми із схемою серіалізації Java за замовчуванням.

Я вважаю, що Binder та AIDL працюють з об'єктами Parcelable.

Однак ви можете використовувати об'єкти, що серіалізуються, у програмах Intents.


1
як я серіалізую об'єкт Parcelable? Як зробити його стійким?
Аїд

@Haded Отримайте вміст стану об'єктів і збережіть його у файлі або базі даних SQLLite. Серіализинг корисний для того, щоб об'єкти переносилися між різними компонентами в андроїд або в різних програмах взагалі.
Джонатан

6
Це чудове пояснення. Я також помітив це: "Посилка не є механізмом серіалізації загального призначення. Цей клас (і відповідний API Parcelable для розміщення довільних об'єктів у посилку) розроблений як високоефективний транспорт IPC. Як такий, він не підходить розміщуйте будь-які дані посилок у постійному сховищі: зміни основної реалізації будь-яких даних у посилці можуть зробити старі дані нечитатими. " developer.android.com/reference/android/os/Parcel.html
Sam003

@Zhisheng, що означає довільні об'єкти? які об’єкти ми можемо помістити в посилку?
hasnain_ahmad

Як щодо перетворення об’єктів у json string замість gson?
ФОО

57

Я розбиваю проти серіалізму .

Для Яви та Котліна

1) Java

Послідовність, простота

Що таке серіалізація?

Serializable - це стандартний інтерфейс 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 лише для класу та його дітей. Це інтерфейс маркера, що означає, що не існує способу реалізації, Java просто зробить все можливе, щоб ефективно його серіалізувати.

  • Проблема такого підходу полягає в тому, що використовується рефлексія, і це повільний процес. Цей механізм також має тенденцію створювати безліч тимчасових об'єктів і спричиняти досить багато сміття.

Роздільний, Швидкість

Що таке Parcelable?

Parcelable - це ще один інтерфейс. Незважаючи на свого суперника (Serializable у випадку, якщо ви забули), він є частиною 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];
    }
};
}

Тепер, Переможець

введіть тут опис зображення

Результати тестів, проведених Філіпом Бро, показують, що Parcelable є в 10 разів швидшим, ніж Serializable. За цим твердженням стоять і інші інженери Google.

Згідно з ними, підхід за замовчуванням Serializable є більш повільним, ніж Parcelable. І ось у нас є угода між двома сторонами! Але НЕ несправедливо порівнювати цих двох взагалі! Тому що з Parcelable ми фактично пишемо спеціальний код. Код, створений спеціально для одного POJO. Таким чином, сміття не створюється, і результати кращі. Але з підходом Serializable за замовчуванням ми покладаємось на процес автоматичної серіалізації Java. Мабуть, цей процес взагалі не є звичним і створює багато сміття! Таким чином, гірші результати.

Стоп стоп !!!!, перш ніж приймати рішення

Тепер є інший підхід . Весь автоматичний процес за Serializable можна замінити спеціальним кодом, який використовує методи writeObject () та readObject (). Ці методи специфічні. Якщо ми хочемо покластися на підхід Serializable у поєднанні з поведінкою спеціальної серіалізації, тоді ми повинні включити ці два методи з такою ж точною підписом, як та, яка наведена нижче:

 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 та користувальницькою Serializable здається справедливим! Результати можуть бути дивовижними! Спеціальний підхід Serializable є більш ніж у 3 рази швидшим для запису та на 1,6 разів швидшим для читання, ніж для Parcelable.

Відредаговано: -----

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. Використання перехідного періоду призведе до того, що серіалізатор ігнорує це поле, а використання необов'язкового дозволить серіалізатору не зламатися, якщо поле відсутнє, але в той же час потрібно буде вказати значення за замовчуванням.

@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)
    }

Для інших цікавих місць


@Farhana Як це зробити для класу даних у kotlin?
Nisarg

@Nisarg Я додав Котліна Serialization, Подивіться.
Фархана

@Farhana Це було дуже проникливим. Я дуже хочу переїхати до котлін на роботі, але мою пропозицію менеджери постійно відхиляють. Мені цікаво, чи можу я отримати орієнтир для Serializable (за допомогою спеціального методу), який, за вашими словами, в 1,6 рази швидший, ніж Parcelable.
Абхінав Кулшрешта

39

Якщо ви хочете бути хорошим громадянином, знайдіть додатковий час для впровадження Parcelable, оскільки він буде працювати в 10 разів швидше та використовуватиме менше ресурсів.

Однак у більшості випадків повільність Serializable не буде помітна. Сміливо використовуйте його, але пам’ятайте, що серіалізація - це дорога операція, тому зведіть її до мінімуму.

Якщо ви намагаєтеся передати список з тисячами серіалізованих об'єктів, цілком можливо, що весь процес займе більше секунди. Це може зробити переходи або обертання від портрета до ландшафту відчути себе дуже мляво.

Джерело до цього моменту: http://www.developerphil.com/parcelable-vs-serializable/


32

У програмі Parcelable розробники записують спеціальний код для маршалінгу та нерозпорядження, щоб він створював менше об'єктів для сміття порівняно з серіалізацією. Продуктивність Parcelable над серіалізацією значно покращується (приблизно в два рази швидше) завдяки цій спеціальній реалізації.

Serializable - це інтерфейс маркера, який означає, що користувач не може маршалити дані відповідно до своїх вимог. Під час серіалізації операція маршалінгу виконується на віртуальній машині Java (JVM) за допомогою API відбиття Java. Це допомагає визначити учасника та поведінку об'єкта Java, але також створює багато сміттєвих об'єктів. Через це процес серіалізації повільний порівняно з Parcelable.

Редагувати: У чому сенс маршируваного та нерозбірливого продажу?

У кількох словах "маршалінг" позначає процес перетворення даних або об'єктів, що надходять у байт-потік, а "демарширування" - це зворотний процес перетворення потоку байтових потоків у їх вихідні дані або об'єкт. Перетворення досягається за допомогою "серіалізації".

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


Досить вдале пояснення навіть без дослівного прикладу. Якраз те, що мені було потрібно для перегляду.
sud007

20

Я фактично буду одним хлопцем, який виступає за серіалізацію. Різниця в швидкості вже не така різка, оскільки пристрої набагато кращі, ніж кілька років тому, а також є інші, більш тонкі відмінності. Докладнішу інформацію див. У моєму щоденнику з цього питання.


1
Дякую за частку. Його менш складний у здійсненні серіалізаційний і компроміс повинен вирішуватися в тих рідкісних випадках і гіпер оптимізації.
Ankan-Zerob

2
Альтернативна точка зору, особливо коли підтримується експериментами та результатами, дуже допомагає. Мені доводиться працювати з багатьма існуючими вихідними кодами на основі Parcelable, і я можу відновити деякі з них зараз, коли я прочитав вашу публікацію в блозі.
Лесь

14

Parcelable - це такий собі стандарт у розробці Android. Але не через швидкість

Роздільний варіант - це рекомендований підхід для передачі даних. Але якщо ви будете правильно використовувати серіалізацію, як показано в цьому репо , ви побачите, що серіалізація іноді буває навіть швидшою, ніж продільна. Або принаймні терміни порівнянні.

Чи парцелябельніший швидше, ніж серіалізаційний?

Звичайна серіалізація Java на середньому пристрої Android (якщо це зроблено правильно *) приблизно в 3,6 рази швидша ніж Parcelable для записів і приблизно в 1,6 рази швидша для читання. Також це доводить, що серіалізація Java (якщо виконано правильно) - це механізм швидкого зберігання, який дає прийнятні результати навіть при відносно великих графіках об'єктів з 11000 об'єктів з 10 полями в кожному.

* Сидентоз полягає в тому, що зазвичай кожен, хто сліпо заявляє, що "Розсипка є швидшим", порівнює це з автоматичною серіалізацією за замовчуванням, яка використовує багато відображення всередині. Це несправедливе порівняння, оскільки Parcelable використовує ручну (і дуже складну) процедуру запису даних у потік. Що зазвичай не згадується, це те, що стандартна Java Serializable згідно з документами також може бути виконана вручну, використовуючи метод writeObject () та readObject (). Для отримання додаткової інформації див. JavaDocs. Ось як це слід зробити для найкращого виконання.

Отже, якщо серіалізація швидше і легше здійснити, чому андроїд взагалі має проділ?

Причина - нативний код. Парцелябел створюється не просто для міжпроцесорного спілкування. Він також може використовуватися для міжкодового зв'язку . Ви можете відправляти та отримувати об'єкти з рідного шару C ++. Це воно.

Що вибрати? Обидва будуть працювати добре. Але я думаю, що Parcelable є кращим вибором, оскільки його рекомендують google, і як ви бачите з цієї теми, це набагато більше цінується.


Чи можете ви розмістити свої джерела? Я б дуже цінував це. Дякую!!
Archie G. Quiñones

2
Таку відповідь я отримав від досвідченого розробника, який працює над проектом, пов'язаним з AOSP, twitter.com/bwdude . Він сказав, що нативний код C ++ для зв'язку зі шаром SDK використовує власну реалізацію Parcelable. Я думаю, він розповідає про цей клас android.googlesource.com/platform/frameworks/native/+/… Я знаю, що це не найкраще пояснення, але це найкраще в мене зараз. Якщо ви знайдете щось інше, обов’язково опублікуйте це тут =)
Максим Тураєв

Бажаю, щоб я міг вас висловити не раз. Я бачив, як чудові фахівці з питань Android та Java шукають відповіді, яку найбільше схвалюють. Відсутність документації дійсно завадила прожекторам для Serializable. Схоже, це ефекти просування конкретного API. Дякую!
pulp_fiction

11

1. Серіалізація

@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

Інтерфейс чого?

  • є стандартним інтерфейсом Java

Швидкість

  • повільніше, ніж Parcelable

2. Розбірний

@see http://developer.android.com/reference/android/os/Parcelable.html

Інтерфейс чого?

  • є android.os інтерфейсом
    • а це означає, що Google розробив Parcelable для кращої роботи на Android

Швидкість

  • швидше (оскільки він оптимізований для використання на розробці Android)

> На завершення

Майте на увазі, що Serializable - це стандартний інтерфейс Java, а Parcelable - для Android Development


Ви також повинні додати їх використання.
Аншул Тяги

7

Існує певна проблема продуктивності щодо марширування та зняття з продажу. Розділення в два рази швидше, ніж серіалізаційний.

Перейдіть за наступним посиланням:

http://www.3Weatherglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development


Так, ви маєте рацію geeksforandroidgeeks.com/android/…
Vivek Kumar Samele

4

Впровадження parcelable може бути швидшим, якщо ви використовуєте плацентируемый плагін в android studio. пошук генератора кодів для парцеляції Android


3

Інтерфейс Serializable можна використовувати так само, як і Parcelable, що призводить до (не набагато) кращих характеристик. Просто перезапишіть ці два способи, щоб обробити ручний процес маршалування та демарширування:

private void writeObject(java.io.ObjectOutputStream out)
    throws IOException
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException

І все-таки мені здається, що розробляючи рідний Android, шлях до Android - це шлях.

Побачити :


2

Я запізнююсь на відповідь, але розміщую з надією, що це допоможе іншим.

З точки зору швидкості , 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
    }

}

1

Розділяється набагато швидше, ніж серіалізується з Binder, оскільки серіалізація використовує відображення і викликає багато ГК. Parcelable - це дизайн, який оптимізується для передачі об'єкта.

Ось посилання на посилання. http://www.developerphil.com/parcelable-vs-serializable/


1

Ви можете використовувати об'єкти, що серіалізуються, у намірах, але під час створення серіалізації об'єкта Parcelable це може дати серйозний виняток, як NotSerializableException. Чи не рекомендується використовувати серіалізаційний за допомогою Parcelable. Тож краще розширити Parcelable об'єктом, який ви хочете використовувати за допомогою пакета та намірів. Оскільки цей Parcelable є специфічним для Android, тому він не має жодних побічних ефектів. :)


0

Серіалізація

Serializable - це інтерпретаційний інтерфейс, який ми можемо називати порожнім інтерфейсом. У ньому немає жодних попередньо реалізованих методів. Serializable збирається перетворити об'єкт у потік байтів. Таким чином, користувач може передавати дані між однією діяльністю до іншої діяльності. Основна перевага серіалізації - це створення та передача даних дуже просто, але це повільний процес порівняння з парцелябельним.

Розбірний

Можливість посилки швидше, ніж серіалізація. Парцел зможе перетворити об'єкт у байт-потік та передати дані між двома діями. Написання коду посилки порівняно з серіалізацією трохи складніше. Він не створює більше тимчасових об'єктів під час передачі даних між двома видами діяльності.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.