Прямые ссылки на публичные уроки для быстрого старта и стабильной индексации lesson-страниц.
На предыдущем уроке мы узнали, что такое объект Intent, как с его помощью открывать новое Activity и передавать простые типы данных. Продолжаем тему и переходим к передаче объектов между Activity.
Рассматривать будем прямые способы передачи данных с помощью интерфейсов Serializable и Parcelable, а также специального класса Bundle.
Тестировать передачу данных будем в рамках демонстрационных Activity. В качестве передаваемого объекта используем класс ExtraWord для хранения изучаемого слова. Создадим объект с тестовыми данными — наша задача передать его во вторую Activity и отобразить одно из свойств в TextView с идентификатором tvText.
val word = ExtraWord( "galaxy", "галактика", )
При попытке передать объект через putExtra появляется ошибка — метод принимает только определённые типы. Среди допустимых значений есть три, которые позволяют передавать именно объекты: это Serializable, Parcelable и Bundle.
Serializable и Parcelable — два интерфейса в Android для сериализации объектов, то есть преобразования их в поток байтов для сохранения или передачи между компонентами приложения. Обратный процесс — десериализация — восстанавливает объекты из сериализованного представления.
Интерфейс Serializable — классический способ сериализации объектов в Java. Интерфейс не имеет методов, но указывает JVM, что объекты этого класса могут быть сериализованы. Он работает, создавая копию объекта в памяти и записывая её в байтовый поток. Serializable подходит для объектов с небольшим объёмом данных — например, объект ExtraWord с несколькими свойствами или типичный объект User с полями id, name и т. д.
Чтобы объект можно было отправить через Extra, достаточно унаследовать класс от интерфейса Serializable — это всё, что нужно сделать:
data class ExtraWord( val original: String, val translate: String, var learned: Boolean = false, ) : Serializable
Что происходит при отправке:
putExtra() и передаём данные в виде пары ключ-значение.Bundle — контейнер для хранения данных. Он может сохранять как примитивные типы, так и сериализованные объекты, реализующие Serializable или Parcelable.Bundle.Для получения объекта обращаемся к свойству intent и вызываем метод getSerializableExtra. Существуют две версии метода с разной сигнатурой:
intent.getSerializableExtra("EXTRA_KEY_WORD", ExtraWord::class.java) intent.getSerializableExtra("EXTRA_KEY_WORD") // deprecated
Первый — более новый — принимает вторым параметром ссылку на класс и автоматически выполняет безопасное приведение типа. Однако он требует API уровня 33, а если минимальная поддерживаемая версия в проекте ниже, метод подсвечивается ошибкой.
Устаревший метод без второго параметра возвращает тип Serializable?, и приведение к нужному типу нужно выполнять вручную — это небезопасное приведение.
Правильное решение — проверять версию API и в зависимости от неё вызывать нужный метод:
val word: ExtraWord = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { intent.getSerializableExtra("EXTRA_KEY_WORD", ExtraWord::class.java) as ExtraWord } else { intent.getSerializableExtra("EXTRA_KEY_WORD") as ExtraWord }
Альтернативный способ — обратиться к свойству extras (бывший метод getExtras()), а затем вызвать getSerializable(). Принцип работы тот же, но это метод класса Bundle, тогда как getSerializableExtra() располагается в классе Intent.
val word2 = intent.extras?.getSerializable("EXTRA_KEY_WORD", ExtraWord::class.java)
Устаревший метод get, возвращающий тип Any, — требует ручного приведения к нужному типу:
val word3 = intent.extras?.get("EXTRA_KEY_WORD")
Рекомендуется использовать первый актуальный способ с проверкой версии API. Остальные варианты приведены для насмотренности — они встречаются в существующих проектах.
Serializable — простой и удобный способ передачи несложных структур данных. Однако для объектов с большим количеством вложенных данных он не очень подходит по двум причинам:
Serializable использует стандартную Java-сериализацию через механизм рефлексии: JVM анализирует объект на лету, что делает процесс относительно медленным.