Android: разница между Parcelable и Serializable?
Почему Android предоставляет 2 интерфейса для сериализации объектов? Могут ли Сериализуемые объекты взаимодействовать с Android? Binder
а файлы AIDL?
17 ответов
В Android мы знаем, что мы не можем просто передавать объекты в действия. Для этого объекты должны иметь интерфейс Serializable или Parcelable.
Сериализуемый
Serializable - это стандартный интерфейс Java. Вы можете просто реализовать интерфейс 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 намного быстрее, чем сериализуемый. Одна из причин этого заключается в том, что мы явно рассказываем о процессе сериализации, а не используем отражение для его вывода. Также очевидно, что код был сильно оптимизирован для этой цели.
Посмотрите на пример ниже (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 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");
//You can pass Arraylist of Parceble obect as below
//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 быстрее, чем сериализуемый интерфейс
- Интерфейс Parcelable требует больше времени для реализации по сравнению с интерфейсом сериализации
- Сериализуемый интерфейс проще в реализации
- Сериализуемый интерфейс создает много временных объектов и вызывает немало мусора
- Parcelable массив может быть передан через Intent в Android
Serializable - это стандартный интерфейс Java. Вы просто помечаете класс Serializable, реализуя интерфейс, и Java автоматически сериализует его в определенных ситуациях.
Parcelable - это специальный интерфейс для Android, где вы сами реализуете сериализацию. Он был создан, чтобы быть намного более эффективным, чем Serializable, и обойти некоторые проблемы со стандартной сериализационной схемой Java.
Я считаю, что Binder и AIDL работают с объектами Parcelable.
Однако вы можете использовать Сериализуемые объекты в Intents.
Parcelable vs Serializable Я называю эти два.
Сериализуемый, Простота
Что такое Сериализуемый?
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.
В Parcelable разработчики пишут собственный код для маршалинга и демаршалинга, поэтому он создает меньше мусорных объектов по сравнению с сериализацией. Благодаря этой пользовательской реализации производительность Parcelable по сравнению с сериализацией значительно улучшается (примерно в два раза быстрее).
Сериализация - это маркерный интерфейс, который подразумевает, что пользователь не может упорядочить данные в соответствии со своими требованиями. При сериализации операция маршалинга выполняется на виртуальной машине Java (JVM) с использованием API отражения Java. Это помогает идентифицировать элемент и поведение объекта Java, но также приводит к созданию большого количества мусорных объектов. Из-за этого процесс сериализации идет медленно по сравнению с Parcelable.
Редактировать: Что означает маршаллинг и демаршаллинг?
В нескольких словах "маршаллинг" относится к процессу преобразования данных или объектов в поток байтов, а "демаршаллинг" - обратный процесс преобразования байта потока байтов в их исходные данные или объект. Преобразование достигается посредством "сериализации".
Parcelable является своего рода стандартом в разработке Android. Но не из-за скорости
Parcelable рекомендуется для передачи данных. Но если вы правильно используете serializable, как показано в этом репозитории, вы увидите, что сериализуемый иногда даже быстрее, чем parcelable. Или, по крайней мере, сроки сопоставимы.
Parcelable быстрее, чем Serializable?
Обычная Java-сериализация на среднем устройстве Android (если все сделано правильно *) примерно в 3,6 раза быстрее, чем Parcelable для записи, и примерно в 1,6 раза быстрее для чтения. Также это доказывает, что Java Serialization (если все сделано правильно) - это быстрый механизм хранения, который дает приемлемые результаты даже при относительно больших графах объектов из 11000 объектов с 10 полями в каждом.
* Смысл в том, что обычно все, кто слепо заявляет, что "Parcelable намного быстрее", сравнивают его с автоматической сериализацией по умолчанию, которая использует много отражения внутри. Это несправедливое сравнение, потому что Parcelable использует ручную (и очень сложную) процедуру записи данных в поток. Что обычно не упоминается, так это то, что стандартную сериализацию Java в соответствии с документами также можно выполнить вручную, используя методы writeObject() и readObject(). Для получения дополнительной информации см. JavaDocs. Вот как это должно быть сделано для лучшей производительности.
Итак, если сериализуемый способ быстрее и проще в реализации, почему у Android вообще есть пакет?
Причина в нативном коде. Parcelable создан не только для межпроцессного взаимодействия. Он также может быть использован для связи между кодами. Вы можете отправлять и получать объекты из собственного уровня C++. Вот и все.
Что выбрать? Оба будут работать хорошо. Но я думаю, что Parcelable - лучший выбор, так как он рекомендован Google, и, как вы можете видеть из этой ветки, он более ценится.
Если вы хотите быть хорошим гражданином, уделите дополнительное время внедрению Parcelable, поскольку он будет работать в 10 раз быстрее и потреблять меньше ресурсов.
Однако в большинстве случаев медлительность Serializable не будет заметна. Не стесняйтесь использовать его, но помните, что сериализация - это дорогостоящая операция, поэтому сведите ее к минимуму.
Если вы пытаетесь передать список с тысячами сериализованных объектов, возможно, весь процесс займет больше секунды. Это может сделать переходы или поворот от портрета до пейзажа очень вялыми.
Источник к этому пункту: http://www.developerphil.com/parcelable-vs-serializable/
Я на самом деле собираюсь быть тем парнем, который выступает за сериализуемый. Разница в скорости уже не так существенна, поскольку устройства намного лучше, чем несколько лет назад, а также есть и другие, более тонкие различия. Смотрите мой блог на вопрос для получения дополнительной информации.
1. Сериализуемый
@see http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html
Интерфейс чего?
- стандартный интерфейс Java
скорость
- медленнее, чем Parcelable
2. Parcelable
@see http://developer.android.com/reference/android/os/Parcelable.html
Интерфейс чего?
- это интерфейс android.os
- это означает, что Google разработал Parcelable для повышения производительности на Android
скорость
- быстрее (потому что он оптимизирован для использования на Android)
> В заключение
Помните, что 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 может быть быстрее, если вы используете плагин paracelable в Android Studio. поиск Android Генератор парсерабельного кода
1. Сериализуемый
Интерфейс — это маркер (интерфейс без абстрактных методов), ничего переопределять не нужно.
2. Разделяемый
Интерфейс с абстрактными методами. При его реализации нужно переопределить все абстрактные методы, указав, какие поля и в каком порядке нужно писать/читать (обычно студия сама их может сгенерировать).
Практически никто не пишет на Котлине. Для этого есть специальная аннотация, благодаря которой реализация этого интерфейса будет сгенерирована автоматически. Для его использования необходимо добавить специальный плагин.
- В build.gradle в разделе плагинов добавьте еще один плагин: id 'kotlin-parcelize'
- Синхронизировать проект
Вам не нужно беспокоиться о реализации методов, все, что вам нужно, это реализовать интерфейс Parcelable и добавить аннотацию @Parcelize .
Все будет хорошо и быстро!
Полученные результаты
Процесс реализации будет быстрее, если вы реализуете интерфейс Parcelable вместо Serializable.
Разборчиво намного быстрее, чем сериализуемое с помощью Binder, потому что сериализуемое использование отражения и вызывает много GC. Parcelable - это дизайн для оптимизации передачи объекта.
Вот ссылка на ссылку. http://www.developerphil.com/parcelable-vs-serializable/
Я опаздываю с ответом, но пишу с надеждой, что это поможет другим.
Что касается скорости,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
}
}
Вы можете использовать сериализуемые объекты в намерениях, но во время сериализации объекта Parcelable это может привести к серьезному исключению, например NotSerializableException. Разве не рекомендуется использовать сериализуемый с Parcelable . Поэтому лучше расширить Parcelable с помощью объекта, который вы хотите использовать в связке и намерениях. Поскольку этот Parcelable специфичен для Android, у него нет побочных эффектов.:)
Parcelable преобразует объект в поток байтов для передачи объекта между процессами в Android.
Сериализация преобразует POJO в строку (строку JSON) и используется на разных платформах для передачи информации об объекте.
Сериализуемый
Serializable - это помечаемый интерфейс, или мы можем вызывать его как пустой интерфейс. У него нет заранее реализованных методов. Serializable будет преобразовывать объект в поток байтов. Таким образом, пользователь может передавать данные из одного действия в другое. Основным преимуществом сериализации является то, что создание и передача данных очень просты, но это медленный процесс по сравнению с parcelable.
Посылочный
Возможность посылки быстрее, чем сериализуемая. Посылка может преобразовывать объект в поток байтов и передавать данные между двумя действиями. Написание кода с возможностью посылки немного сложнее по сравнению с сериализацией. Он не создает дополнительных временных объектов при передаче данных между двумя действиями.