Как передавать параметры в Android через Intent, Bundle и query parameters
Короткий ответ: для обмена между Activity/Fragment используйте Intent extras/Bundle (примитивы и Parcelable), для deep links и навигации — query parameters в URI; для больших объектов передавайте только id и храните данные во ViewModel/DB.
Intent extras и Bundle — быстрое руководство с примерами
Отправка простых типов — через putExtra, ключи лучше хранить в константах:
// Отправитель
val intent = Intent(this, DetailActivity::class.java).apply {
putExtra(EXTRA_USER_ID, 123L)
putExtra(EXTRA_NAME, "Иван Иванов")
}
startActivity(intent)
// Получатель
val userId = intent.getLongExtra(EXTRA_USER_ID, -1L)
val name = intent.getStringExtra(EXTRA_NAME) ?: "Неизвестно"
Для Fragment — устанавливайте arguments до attach():
val bundle = Bundle().apply { putParcelable("user", user) }
val frag = DetailFragment().apply { arguments = bundle }
Ключи для extras храните как const val в companion object, чтобы избежать опечаток.
Передача объектов: Parcelable vs Serializable vs JSON
Используйте Parcelable (или @Parcelize) для собственных моделей — быстрее и компактнее. Serializable — запасной вариант для сторонних классов. Для кросс-платформенных/удалённых передач — JSON строка.
Сравнение способов передачи объектов
| Способ | Производительность | Размер | Когда применять |
|---|---|---|---|
| Parcelable | Очень быстро | Меньше | Собственные модели |
| Serializable | Медленнее | Больше | Legacy/библиотеки |
| JSON (String) | Средне | Больше | Для логирования/интернета |
Пример @Parcelize:
@Parcelize
data class User(val id: Long, val name: String, val email: String) : Parcelable
intent.putExtra("user", user)
val received: User? = intent.getParcelableExtra("user")
Query parameters, deep links и Navigation Component (Compose)
Для deep link используйте Uri с query-параметрами:
val uri = Uri.parse("app://detail").buildUpon()
.appendQueryParameter("id", "456")
.appendQueryParameter("filter", "new")
.build()
val intent = Intent(Intent.ACTION_VIEW, uri)
startActivity(intent)
В Activity/Fragment получить:
val id = intent.data?.getQueryParameter("id")
В Jetpack Navigation (Compose) аргументы парсятся через NavType:
composable(
"detail/{id}?filter={filter}",
arguments = listOf(
navArgument("id") { type = NavType.LongType },
navArgument("filter") { defaultValue = "all"; nullable = true }
)
) { backStackEntry ->
val id = backStackEntry.arguments?.getLong("id")
if (id == null) { /* обработать, finish() или показать ошибку */ }
}
Для динамических экранов (поиск, фильтры) query-параметры удобнее; для важных данных — передавайте id и загружайте модель через ViewModel/репозиторий.
Безопасные геттеры и совместимость с Android 13+ (TIRAMISU)
Используйте универсальный метод для получения Parcelable, чтобы избегать ClassCastException на новых API:
inline fun <reified T : Parcelable> Intent.getParcelableSafe(key: String): T? =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableExtra(key, T::class.java)
} else {
@Suppress("DEPRECATION")
getParcelableExtra(key) as? T
}
Частые ошибки
- Не проверять null: всегда использовать дефолтные значения или requireNotNull.
- Хранить большие объекты в extras — риск OOM/медленной сериализации.
- Менять ключи extras без бэкапа — краши при чтении старых Intent.
- Передавать mutable ссылки между Activity/Fragment — утечки памяти.
FAQ
- Как передать список объектов? — Лучше сериализовать в ParcelableArrayList или передать id-list и восстановить модель из репозитория.
- Что безопаснее: query params или extras? — Для навигации/ссылок — query params; для приватных данных между компонентами — extras.
- Как избежать NullPointerException при парсинге id? — Используйте getLongExtra с дефолтом или проверку на null и finish()/showError.
- Когда применять Safe Args? — При использовании Navigation Component: генерирует типобезопасный код и уменьшает ошибки с ключами.
Не передавайте пользовательские пароли или токены через Intent/URI — используйте безопасное хранилище (Keystore) и передавайте только маркеры/идентификаторы.