Достаточно часто бывает ситуация, когда нам нужно передать данные между компонентами (например, между двумя активити или даже приложениями). И один из популярных способов сделать это — Parcelable. Этот интерфейс позволяет записать объекты в Parcel, который затем может быть передан между компонентами.
Но есть большая проблема, что при изменении структуры данных в Parcelable могут возникнуть проблемы с совместимостью. И недавно я обнаружила метод setDataPosition.
Что такое setDataPosition
setDataPosition — это такой метод класса Parcel, который устанавливает текущую позицию чтения/записи. Благодаря этому методу мы можем перемещаться по данным внутри Parcel и читать/записывать значения в нужных местах (https://developer.android.com/reference/android/os/Parcel#setDataPosition(int)).
Пример:
Теперь представим, что нам нужно добавить новый параметр id для котика.
Добавление нового параметра и проблемы совместимости
Мы добавляем новый параметр id и изменяем методы writeToParcel и createFromParcel, добавляя туда writeInt и readInt:
Если мы попробуем прочитать котика, сохраненного старой версией приложения (без id), используя новый код, это приведет к ошибке, так как Parcel будет ожидать дополнительное значение id, а его нет. И наоборот тоже.
Используем setDataPosition для решения проблемы
Чтобы поддержать обратную совместимость, мы можем использовать setDataPosition для корректного чтения данных, сохраняя прежний формат для старых версий.
Как работает
- Мы сохраняем начальную позицию с помощью parcel.dataPosition().
- Сначала пытаемся прочитать новый формат c id.
- Если чтение id приводит к исключению, значит, данные находятся в старом формате. Мы возвращаемся к начальной позиции и читаем данные без id.
- Везде пишут про исключение, но у меня, возвращалось -1. Так что перепроверяйте, что там действительно бросается исключение.
В итоге, этот метод позволяет поддерживать совместимость между разными версиями приложения, что сильно выручает, если изначально нет версионности в апи.
Дубль статей в телеграмме — https://t.me/android_junior
Мои заметки в телеграмме — https://t.me/android_junior_notes