Android Studio Kotlin уроки: передача данных из Activity

В любом приложении, где больше одного экрана, возникает задача — передать информацию от одной Activity к другой. Это может быть текст, который ввёл пользователь, выбранный пункт списка, настройки или даже целый объект. В этом уроке из серии android studio kotlin уроки мы разберём все основные способы передачи данных между Activity, от самых простых до современных и рекомендованных.

Intent и putExtra: классический способ

Intent — это универсальный «курьер» в Android, который не только запускает новые Activity, но и может нести с собой данные. Для упаковки данных используется метод putExtra(), принимающий два аргумента: строковый ключ и само значение. Этот подход поддерживает все примитивные типы (String, Int, Boolean и т.д.), их массивы, а также объекты, реализующие интерфейс Serializable.

Рассмотрим классический пример. У нас есть MainActivity с полем ввода и кнопкой, по нажатию на которую мы передаём введённый текст в SecondActivity и открываем её.


Отправка данных (MainActivity.kt)

val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("USER_NAME", binding.editText.text.toString())
intent.putExtra("USER_AGE", 25)
startActivity(intent)


Получение данных (SecondActivity.kt)

val userName = intent.getStringExtra("USER_NAME") ?: "Гость"
val userAge = intent.getIntExtra("USER_AGE", 0)

binding.textView.text = "Привет, $userName! Тебе $userAge лет."


Важно: для каждого типа данных существует свой метод получения: getStringExtra(), getIntExtra(), getBooleanExtra() и так далее. Второй параметр у числовых методов — это значение по умолчанию, которое вернётся, если ключ не найден.


Bundle: контейнер для сложных данных

Если данных много, удобно собрать их в объект Bundle. Bundle — это хранилище пар «ключ-значение», похожее на Intent, но позволяющее группировать данные и передавать их единым блоком. С Bundle код становится чище, особенно когда нужно передать большой набор параметров.

// Отправка
val bundle = Bundle().apply {
    putString("NAME", "Анна")
    putInt("SCORE", 95)
    putBoolean("IS_PREMIUM", true)
}
val intent = Intent(this, SecondActivity::class.java).apply { putExtras(bundle) }
startActivity(intent)

// Получение
val bundle = intent.extras
val name = bundle?.getString("NAME") ?: "Гость"
val score = bundle?.getInt("SCORE") ?: 0

Такой подход особенно полезен, когда данные передаются через несколько экранов или когда они приходят из другого источника (например, push-уведомления).


Передача объектов: Parcelable

Передавать отдельные строки и числа — это хорошо, но в реальных приложениях гораздо чаще нужно передать целый объект: данные пользователя, товар, заказ. Для этого в Android есть два основных механизма: Serializable (медленный, но простой) и Parcelable (быстрый, но требует больше кода). Google рекомендует использовать именно Parcelable, а Kotlin делает это невероятно простым благодаря аннотации @Parcelize.

Для использования @Parcelize добавьте в build.gradle.kts (модуль app) плагин:

plugins {
    id("kotlin-parcelize")
}

Теперь создадим data-класс, реализующий Parcelable:

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class User(
    val id: Int,
    val name: String,
    val email: String
) : Parcelable

Передача объекта:

// Отправка
val user = User(1, "Алексей", "alex@example.com")
val intent = Intent(this, SecondActivity::class.java)
intent.putExtra("USER_DATA", user)
startActivity(intent)

// Получение
val user = intent.getParcelableExtra<User>("USER_DATA")
user?.let {
    binding.textView.text = "Пользователь: ${it.name}, Email: ${it.email}"
}

Использование Parcelable гораздо эффективнее Serializable, особенно при частых передачах или работе с большими объектами.


Возврат данных: Activity Result API

Иногда нужно не просто передать данные в другую Activity, но и получить результат обратно. Раньше для этого использовали методы startActivityForResult() и onActivityResult(), но они давно объявлены устаревшими (deprecated). Современный подход — Activity Result API, который проще, безопаснее и не требует ручного управления кодами запросов.

Вот как это работает. Сначала в первой Activity регистрируем «ланчер» — специальный объект, который будет запускать вторую Activity и обрабатывать результат:

private val launcher = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val returnedData = result.data?.getStringExtra("RESULT_KEY")
        binding.textView.text = "Получено: $returnedData"
    }
}

Затем запускаем вторую Activity через этот ланчер:

val intent = Intent(this, SecondActivity::class.java)
launcher.launch(intent)

Во второй Activity формируем результат и закрываем экран:

val resultIntent = Intent().apply {
    putExtra("RESULT_KEY", "Данные со второго экрана")
}
setResult(Activity.RESULT_OK, resultIntent)
finish()

Преимущества Activity Result API очевидны: код обработки результата находится рядом с кодом запуска, не нужно думать о requestCode, и всё это безопасно работает с жизненным циклом компонентов.


Альтернативные способы и когда их не стоит использовать

Кроме Intent, существуют и другие механизмы обмена данными между Activity, но у каждого есть свои нюансы:

  • Глобальные переменные (static, companion object) — крайне ненадёжный способ. Данные теряются при пересоздании Activity (поворот экрана, сворачивание приложения) и могут вызывать утечки памяти. Используйте только для констант.
  • SharedPreferences / DataStore — отлично подходят для долговременного хранения настроек, но не для передачи данных между экранами в рамках одного сеанса. Операции записи/чтения медленные и асинхронные.
  • База данных (Room) — подходит для сложных структур данных, которые нужны в разных частях приложения. Но для простой передачи строки или числа — это как «стрелять из пушки по воробьям».
  • ViewModel — идеальный инструмент для хранения данных, связанных с конкретным экраном, но не для передачи между независимыми Activity (ViewModel привязана к жизненному циклу конкретной Activity). Однако если вы используете Single Activity архитектуру с фрагментами, общий ViewModel — лучший выбор.
  • Event Bus (LiveData, Flow) — может использоваться для коммуникации между компонентами, но злоупотребление ими усложняет отладку и понимание потоков данных.



Сводная таблица: какой метод выбрать?

СитуацияРекомендуемый метод
Передать 1–2 простых значенияIntent + putExtra
Передать много параметровBundle
Передать объект (User, Product и т.д.)Parcelable с @Parcelize
Получить результат обратноActivity Result API
Общие данные для нескольких фрагментовShared ViewModel
Долговременное хранение настроекDataStore / SharedPreferences


Итоги

Мы разобрали ключевые способы передачи данных между Activity в рамках android studio kotlin уроки. Базовый Intent с putExtra() отлично подходит для простых сценариев, Bundle помогает структурировать множество параметров, Parcelable позволяет передавать сложные объекты, а Activity Result API — современный стандарт для получения обратной связи. Выбирайте метод в зависимости от задачи, и ваше приложение будет работать предсказуемо и надёжно. Практикуйтесь, экспериментируйте, и совсем скоро передача данных станет для вас рутинной и понятной операцией!