Что такое сериализация и десереализация?
Сериализация - это процесс перевода структуры данных в последовательность байтов.
Десериализация - это процесс перевода байтов в структуры данных.
Изначально в java есть Serializable, но так как она медленная из-за использования рефлексии, Android решили сделать некое подобие Serializable и назвали его Parcelable.
Parcelable быстрее так как это некий контейнер данных, что-то вроде стека, в который загружаются данные объекта.
ВАЖНО!
Есть метод:
Parcel.marshal()
Массив байт, который мы получили с помощью этого метода слишком большой и его НЕЛЬЗЯ хранить в постоянной памяти, так как в андроиде частое межпроцессное взаимодействие.
Именно поэтому иногда до сих пор можно увидеть Serializable классы в проекте.
Serializable and Parcelable are both ways to pass data between activities or fragments in Android, but they work in slightly different ways.
Serializable is a Java interface that allows objects to be written to and read from a stream. It is simple to use, but it can be slower than Parcelable because it needs to convert the object to a byte stream before it can be passed.
Parcelable is an Android specific interface that allows objects to be passed between activities or fragments more efficiently. It directly writes the object's fields to and from a Parcel, which is a container for a message (data and object references) that can be sent through an IBinder. It is faster than Serializable but it requires a bit more work to implement.
In summary, Serializable is a standard Java interface that is easy to use, but can be slower. Parcelable is an Android-specific interface that is faster but more complex to implement.
Serializable
Serializable содержит внутри себя рефлексию reflection API. Это механизм исследования данных о программе во время ее выполнения.
Плюсы:
- Можно сохранять в постоянном хранилище.
Минусы сериализации:
- Медленно. Прежде чем обратиться к объектам, сначала надо их исследовать.
- Потребление памяти. Во время исследования создаются доп. объекты.
- Частый вызов Garbage collector как раз из-за большого потребления памяти.
Управление Serializable:
- По хорошему должны переопределять поле serialVersionUID
companion object{
const val **serialVersionUID** = -344353453234L
}
Благодаря этому, если мы изменим какое-то поле, при десериализации будет происходить сравнение объектов по serialVersionUID и мы гарантировано получим то поле, которое поменяли.
2. Помечать поле аннотацией @Transient. Поля помеченные этой аннотацией не будут сериализовываться или десериализовываться. @Transient полезно использовать, когда работаем с какими-то чувствительными данными, например пароль и мы не хотим ими светить и сохранять где-то.
3. Использовать Externalizable. Используя его мы можем как в Parcelable сохранять данные и в таком же порядке читать.
4. Serializable(writeObject/readObject)
Parcelable
Parcelable если визуализировать, то он представляет некий стек данных, в котором мы поочередно записываем данные и потом их считываем.
Плюсы:
- БЫСТРАЯ ОБРАБОТКА
- ТРЕБУЕТ МЕНЬШЕ МЕСТА
- Не завязываемся на имя переменной, как это было в Serializable .
- Не нужно сериализовывать эти переменные.
- Мы создаем объект сами, нам не надо искать через рефлексию конструктор, как-то создавать объект.
Минусы:
- Нельзя использовать в постоянном хранилище.
- Все таки содержит иногда рефлексию. Например при переопределении поля. В java переопределять поле нельзя, только методы, поэтому в случае с parcelable исопльзуется для этого рефлексия.
Ограничения:
Например Bundle при передачи данных из одной активности в другую.
Когда мы стартуем Intent, он проходит через IBinder интерфейс, который имеет ограничение на транзацию в 1мб, поэтому если мы передадим через Bundle данные, превышающие 1мб, у нас будет исключение о большом размере транзакции.