Чому Android надає 2 інтерфейси для серіалізації об’єктів? Чи взаємодіють об'єкти серіалізації з файлами Android Binder
та AIDL?
Чому Android надає 2 інтерфейси для серіалізації об’єктів? Чи взаємодіють об'єкти серіалізації з файлами Android Binder
та AIDL?
Відповіді:
В 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");
Висновок
Parcelable
швидше Serializable
інтерфейсуParcelable
Інтерфейс займає більше часу на реалізацію порівняно з Serializable
інтерфейсомSerializable
інтерфейс простіший в реалізації Serializable
інтерфейс створює безліч тимчасових об'єктів і спричиняє досить багато сміттяParcelable
масив може бути переданий за допомогою Intent в androidSerializable - це стандартний інтерфейс Java. Ви просто позначите клас Serializable, реалізуючи інтерфейс, і Java автоматично серіалізує його в певних ситуаціях.
Parcelable - це специфічний для Android інтерфейс, де ви реалізуєте серіалізацію самостійно. Він був створений для того, щоб бути набагато ефективнішим, ніж серіалізація, і щоб обійти деякі проблеми із схемою серіалізації Java за замовчуванням.
Я вважаю, що Binder та AIDL працюють з об'єктами Parcelable.
Однак ви можете використовувати об'єкти, що серіалізуються, у програмах Intents.
Я розбиваю проти серіалізму .
Для Яви та Котліна
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)
}
Serialization
, Подивіться.
Якщо ви хочете бути хорошим громадянином, знайдіть додатковий час для впровадження Parcelable, оскільки він буде працювати в 10 разів швидше та використовуватиме менше ресурсів.
Однак у більшості випадків повільність Serializable не буде помітна. Сміливо використовуйте його, але пам’ятайте, що серіалізація - це дорога операція, тому зведіть її до мінімуму.
Якщо ви намагаєтеся передати список з тисячами серіалізованих об'єктів, цілком можливо, що весь процес займе більше секунди. Це може зробити переходи або обертання від портрета до ландшафту відчути себе дуже мляво.
Джерело до цього моменту: http://www.developerphil.com/parcelable-vs-serializable/
У програмі Parcelable розробники записують спеціальний код для маршалінгу та нерозпорядження, щоб він створював менше об'єктів для сміття порівняно з серіалізацією. Продуктивність Parcelable над серіалізацією значно покращується (приблизно в два рази швидше) завдяки цій спеціальній реалізації.
Serializable - це інтерфейс маркера, який означає, що користувач не може маршалити дані відповідно до своїх вимог. Під час серіалізації операція маршалінгу виконується на віртуальній машині Java (JVM) за допомогою API відбиття Java. Це допомагає визначити учасника та поведінку об'єкта Java, але також створює багато сміттєвих об'єктів. Через це процес серіалізації повільний порівняно з Parcelable.
Редагувати: У чому сенс маршируваного та нерозбірливого продажу?
У кількох словах "маршалінг" позначає процес перетворення даних або об'єктів, що надходять у байт-потік, а "демарширування" - це зворотний процес перетворення потоку байтових потоків у їх вихідні дані або об'єкт. Перетворення досягається за допомогою "серіалізації".
Я фактично буду одним хлопцем, який виступає за серіалізацію. Різниця в швидкості вже не така різка, оскільки пристрої набагато кращі, ніж кілька років тому, а також є інші, більш тонкі відмінності. Докладнішу інформацію див. У моєму щоденнику з цього питання.
Роздільний варіант - це рекомендований підхід для передачі даних. Але якщо ви будете правильно використовувати серіалізацію, як показано в цьому репо , ви побачите, що серіалізація іноді буває навіть швидшою, ніж продільна. Або принаймні терміни порівнянні.
Звичайна серіалізація Java на середньому пристрої Android (якщо це зроблено правильно *) приблизно в 3,6 рази швидша ніж Parcelable для записів і приблизно в 1,6 рази швидша для читання. Також це доводить, що серіалізація Java (якщо виконано правильно) - це механізм швидкого зберігання, який дає прийнятні результати навіть при відносно великих графіках об'єктів з 11000 об'єктів з 10 полями в кожному.
* Сидентоз полягає в тому, що зазвичай кожен, хто сліпо заявляє, що "Розсипка є швидшим", порівнює це з автоматичною серіалізацією за замовчуванням, яка використовує багато відображення всередині. Це несправедливе порівняння, оскільки Parcelable використовує ручну (і дуже складну) процедуру запису даних у потік. Що зазвичай не згадується, це те, що стандартна Java Serializable згідно з документами також може бути виконана вручну, використовуючи метод writeObject () та readObject (). Для отримання додаткової інформації див. JavaDocs. Ось як це слід зробити для найкращого виконання.
Причина - нативний код. Парцелябел створюється не просто для міжпроцесорного спілкування. Він також може використовуватися для міжкодового зв'язку . Ви можете відправляти та отримувати об'єкти з рідного шару C ++. Це воно.
Що вибрати? Обидва будуть працювати добре. Але я думаю, що Parcelable є кращим вибором, оскільки його рекомендують google, і як ви бачите з цієї теми, це набагато більше цінується.
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
@see http://developer.android.com/reference/android/os/Parcelable.html
Майте на увазі, що Serializable - це стандартний інтерфейс Java, а Parcelable - для Android Development
Існує певна проблема продуктивності щодо марширування та зняття з продажу. Розділення в два рази швидше, ніж серіалізаційний.
Перейдіть за наступним посиланням:
http://www.3Weatherglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
Впровадження parcelable може бути швидшим, якщо ви використовуєте плацентируемый плагін в android studio. пошук генератора кодів для парцеляції Android
Інтерфейс Serializable можна використовувати так само, як і Parcelable, що призводить до (не набагато) кращих характеристик. Просто перезапишіть ці два способи, щоб обробити ручний процес маршалування та демарширування:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
І все-таки мені здається, що розробляючи рідний Android, шлях до Android - це шлях.
Побачити :
Я запізнююсь на відповідь, але розміщую з надією, що це допоможе іншим.
З точки зору швидкості , 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
}
}
Розділяється набагато швидше, ніж серіалізується з Binder, оскільки серіалізація використовує відображення і викликає багато ГК. Parcelable - це дизайн, який оптимізується для передачі об'єкта.
Ось посилання на посилання. http://www.developerphil.com/parcelable-vs-serializable/
Ви можете використовувати об'єкти, що серіалізуються, у намірах, але під час створення серіалізації об'єкта Parcelable це може дати серйозний виняток, як NotSerializableException. Чи не рекомендується використовувати серіалізаційний за допомогою Parcelable. Тож краще розширити Parcelable об'єктом, який ви хочете використовувати за допомогою пакета та намірів. Оскільки цей Parcelable є специфічним для Android, тому він не має жодних побічних ефектів. :)
Серіалізація
Serializable - це інтерпретаційний інтерфейс, який ми можемо називати порожнім інтерфейсом. У ньому немає жодних попередньо реалізованих методів. Serializable збирається перетворити об'єкт у потік байтів. Таким чином, користувач може передавати дані між однією діяльністю до іншої діяльності. Основна перевага серіалізації - це створення та передача даних дуже просто, але це повільний процес порівняння з парцелябельним.
Розбірний
Можливість посилки швидше, ніж серіалізація. Парцел зможе перетворити об'єкт у байт-потік та передати дані між двома діями. Написання коду посилки порівняно з серіалізацією трохи складніше. Він не створює більше тимчасових об'єктів під час передачі даних між двома видами діяльності.