Почему 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
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, где вы сами реализуете сериализацию. Он был создан, чтобы быть намного более эффективным, чем Serializable, и обойти некоторые проблемы со стандартной сериализационной схемой Java.
Я считаю, что Binder и AIDL работают с объектами Parcelable.
Однако вы можете использовать Сериализуемые объекты в Intents.
Parcelable vs Serializable Я называю эти два.
Для Явы и Котлина
1) Ява
Сериализуемый, Простота
Что такое Сериализуемый?
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 заключается в том, что вам нужно реализовать интерфейс Serializable только для класса и его потомков. Это маркерный интерфейс, означающий, что метод для реализации не существует, Java просто сделает все возможное для его эффективной сериализации.
Проблема этого подхода заключается в том, что используется рефлексия, и это медленный процесс. Этот механизм также имеет тенденцию создавать много временных объектов и вызывать довольно много мусора.
Parcelable, Скорость
Что такое 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 и Custom Serializable кажется справедливым! Результаты могут быть удивительными! Настраиваемый Serializable подход более чем в 3 раза быстрее для записи и в 1,6 раза быстрее для чтения, чем Parcelable.
Отредактировано: -----
2) Сериализация Kotlinx
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.
Редактировать: Что означает маршаллинг и демаршаллинг?
В нескольких словах, «маршаллинг» относится к процессу преобразования данных или объектов в байтовый поток, а «демаршаллинг» - это обратный процесс преобразования байтового потока в их исходные данные или объект. Преобразование достигается через «сериализацию».
Я на самом деле собираюсь быть тем парнем, который защищает Serializable. Разница в скорости уже не так существенна, поскольку устройства намного лучше, чем несколько лет назад, а также есть и другие, более тонкие различия. Смотрите мой блог на вопрос для получения дополнительной информации.
Parcelable рекомендуется для передачи данных. Но если вы правильно используете serializable, как показано в этом репозитории , вы увидите, что сериализуемый иногда даже быстрее, чем parcelable. Или, по крайней мере, сроки сопоставимы.
Обычная сериализация Java на среднем устройстве Android (если все сделано правильно *) примерно в 3,6 раза быстрее, чем Parcelable для записи, и примерно в 1,6 раза быстрее для чтения. Также это доказывает, что Java Serialization (если все сделано правильно) - это быстрый механизм хранения, который дает приемлемые результаты даже при относительно больших графах объектов из 11000 объектов с 10 полями в каждом.
* Смысл в том, что обычно каждый, кто слепо заявляет, что «Parcelable намного быстрее», сравнивает его с автоматической сериализацией по умолчанию, которая использует много отражения внутри. Это несправедливое сравнение, потому что Parcelable использует ручную (и очень сложную) процедуру записи данных в поток. Что обычно не упоминается, так это то, что стандартную сериализацию Java в соответствии с документами также можно выполнить вручную, используя методы writeObject () и readObject (). Для получения дополнительной информации см. JavaDocs. Вот как это должно быть сделано для лучшей производительности.
Причина в нативном коде. Parcelable создан не только для межпроцессного взаимодействия. Он также может быть использован для связи между кодами . Вы можете отправлять и получать объекты из собственного уровня 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.
Существует некоторая проблема производительности, связанная с маршалингом и демаршалингом. Parcelable в два раза быстрее, чем Serializable.
Пожалуйста, перейдите по следующей ссылке:
http://www.3pillarglobal.com/insights/parcelable-vs-java-serialization-in-android-app-development
Реализация parcelable может быть быстрее, если вы используете плагин paracelable в 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 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
}
}
Разборчиво гораздо быстрее, чем сериализуемое с помощью Binder, потому что сериализуемое использование отражения и вызывает много GC. Parcelable - это дизайн для оптимизации передачи объекта.
Вот ссылка на ссылку. http://www.developerphil.com/parcelable-vs-serializable/
вы можете использовать сериализуемые объекты в намерениях, но во время сериализации объекта Parcelable это может привести к серьезному исключению, например NotSerializableException. Разве не рекомендуется использовать сериализуемый с Parcelable. Поэтому лучше расширить Parcelable объектом, который вы хотите использовать с помощью связки и намерений. Поскольку этот Parcelable специфичен для Android, у него нет побочных эффектов. :)
Сериализуемый
Serializable - это маркируемый интерфейс, или мы можем назвать его пустым интерфейсом. У него нет предварительно реализованных методов. Serializable собирается преобразовать объект в поток байтов. Таким образом, пользователь может передавать данные между одним действием другому. Основное преимущество сериализуемого заключается в том, что создание и передача данных очень просты, но это медленный процесс по сравнению с возможностью их рассылки.
Parcelable
Посылка способна быстрее, чем сериализуемая. Parcel способен конвертировать объект в поток байтов и передавать данные между двумя действиями. Написание кода для посылок немного сложнее по сравнению с сериализацией. Он не создает больше временных объектов при передаче данных между двумя действиями.