Jetpack Compose — первый экран
Jetpack Compose — первый экран
Где применяют Compose на Android
Jetpack Compose — способ строить интерфейс Android на Kotlin-функциях, а не в XML. Вы описываете «при таком состоянии экран выглядит так»; при изменении числа, текста или списка фреймворк перерисовывает только нужные части (recomposition).
Общий UI на нескольких платформах — Compose Multiplatform. Теория: экосистема Kotlin. Фоновая работа: корутины, Flow.
Словарь терминов
| Термин | Простыми словами |
|---|---|
| Activity | Окно приложения на Android; точка входа экрана. |
@Composable | Функция, которая рисует UI. |
| State (состояние) | Данные, от которых зависит картинка (число счётчика, текст поля). |
remember | Сохранить состояние между перерисовками. |
| ViewModel | Объект, который переживает поворот экрана и хранит данные экрана. |
StateFlow | Поток «последнее значение состояния» для UI. |
| NavHost | Контейнер нескольких экранов и переходов между ними. |
Что получится
Экран со счётчиком на Material3: remember для локального состояния и опционально ViewModel, чтобы счётчик не сбрасывался при повороте телефона.
Создание проекта
Android Studio: New Project → Empty Activity (или Empty Compose Activity).
Фрагмент app/build.gradle.kts:
android {
buildFeatures { compose = true }
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
}
dependencies {
implementation(platform("androidx.compose:compose-bom:2024.06.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.activity:activity-compose:1.9.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.0")
}
compose-bom согласует версии библиотек Compose. minSdk 24–26 — типичный минимум для новых проектов.
MainActivity — подключение Compose
package com.example.demo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MaterialTheme {
Surface {
CounterScreen()
}
}
}
}
}
| Элемент | Роль |
|---|---|
ComponentActivity | Базовая Activity с поддержкой Compose. |
setContent { } | «Корень» UI на Compose вместо setContentView(R.layout...). |
MaterialTheme | Цвета и типографика Material. |
Surface | Фон и отступы контента. |
Состояние на экране
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun CounterScreen() {
var count by remember { mutableStateOf(0) }
Column(
modifier = Modifier.fillMaxSize().padding(24.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text("Счётчик: $count", style = MaterialTheme.typography.headlineMedium)
Button(onClick = { count++ }) {
Text("Увеличить")
}
OutlinedButton(onClick = { count = 0 }) {
Text("Сбросить")
}
}
}
Разбор API
| API | Назначение |
|---|---|
@Composable | Помечает функцию UI; вызывается только из Composable или setContent. |
remember { mutableStateOf(0) } | Один раз создать состояние 0, хранить между recomposition. |
by | Делегат: писать count++, а не count.value++. |
mutableStateOf | При изменении значения Compose планирует перерисовку. |
Column | Вертикальная раскладка. |
Modifier.fillMaxSize().padding(24.dp) | Размер и отступы. |
Без remember при каждой перерисовке count снова стал бы 0.
ViewModel — состояние переживает поворот
При повороте Activity пересоздаётся; remember внутри Composable без ViewModel тоже сбросится. Решение — вынести данные в ViewModel:
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
data class CounterUiState(val count: Int = 0)
class CounterViewModel : ViewModel() {
private val _state = MutableStateFlow(CounterUiState())
val state: StateFlow<CounterUiState> = _state.asStateFlow()
fun increment() = _state.update { it.copy(count = it.count + 1) }
fun reset() = _state.update { CounterUiState() }
}
Экран:
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
@Composable
fun CounterScreen(vm: CounterViewModel = viewModel()) {
val uiState by vm.state.collectAsState()
Column(Modifier.padding(24.dp)) {
Text("Счётчик: ${uiState.count}")
Button(onClick = vm::increment) { Text("+1") }
OutlinedButton(onClick = vm::reset) { Text("Сброс") }
}
}
| Строка | Смысл |
|---|---|
viewModel() | Получить или создать VM, привязанную к Activity / NavBackStackEntry. |
collectAsState() | Подписаться на StateFlow и получать значение для Composable. |
vm::increment | Ссылка на метод — удобная передача в onClick. |
Загрузка данных с сети
Типичная связка: Ktor Client + viewModelScope:
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.launch
class NotesViewModel(private val api: NotesApi) : ViewModel() {
private val _state = MutableStateFlow<List<Note>>(emptyList())
val state = _state.asStateFlow()
init {
viewModelScope.launch {
_state.value = api.fetchNotes()
}
}
}
В UI: CircularProgressIndicator, пока список пуст; ошибки — поле в UiState или Snackbar. Постоянное хранение на устройстве — Room.
Навигация между экранами
implementation("androidx.navigation:navigation-compose:2.7.7")
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
@Composable
fun AppNav() {
val nav = rememberNavController()
NavHost(navController = nav, startDestination = "home") {
composable("home") {
CounterScreen(onOpenDetails = { nav.navigate("details") })
}
composable("details") {
DetailsScreen(onBack = { nav.popBackStack() })
}
}
}
startDestination — первый экран. navigate / popBackStack — вперёд и назад.
Preview в Android Studio
import androidx.compose.ui.tooling.preview.Preview
@Preview(showBackground = true)
@Composable
fun CounterPreview() {
MaterialTheme {
CounterScreen()
}
}
Preview рисует Composable без запуска эмулятора — быстрая вёрстка.
Compose и XML
Новые экраны пишут на Compose. Старые View можно встроить через AndroidView и мигрировать постепенно. Для нового проекта выбирайте шаблон с Compose сразу.
Частые ошибки
| Симптом | Причина |
|---|---|
@Composable invocations can only happen... | Вызов Composable из обычной функции |
| Счётчик сбрасывается при повороте | Только remember, нет ViewModel / rememberSaveable |
| Preview пустой | Нет обёртки MaterialTheme |
| Красный Gradle sync | Несовместимые версии Compose BOM и Kotlin |
Что попробовать
OutlinedTextField+LazyColumnсо списком заметок.- Второй экран через Navigation Compose.
- Вынести
CounterScreenвcommonMainCMP.
Связанные материалы
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). История Kotlin - создание языка JetBrains для плавной совместимости с Java и современной разработки. Экосистема Kotlin-приложений - инструменты, фреймворки и мультиплатформенные сценарии разработки. Kotlin — это современный язык программирования общего назначения, который работает на платформе Java Virtual Machine (JVM), а также компилируется в JavaScript или нативный код. Набор советов, правил, принципов и обычаев в разработке на этом языке. Основы Kotlin - архитектура проекта, платформенные модули и базовые принципы разработки на языке. Типизация, набор правил определения типа данных значений языка. Операторы и выражения в Kotlin - логика вычислений, приоритеты операций и идиоматичный стиль записи условий. Циклы и управляющие конструкции в Kotlin - идиоматичные способы итерации, условия и управление выполнением. ООП в Kotlin - классы, модификаторы доступа, наследование и идиоматичное проектирование объектных структур. Кавычки, точки, запятые, скобки и прочие знаки препинания. Kotlin использует набор зарезервированных слов для построения синтаксических конструкций языка. Все ключевые слова разделены на категории по назначению. Набор функций, которые включены в стандартную библиотеку языка.История языка Kotlin
Экосистема Kotlin-приложений
Что требуется знать перед началом изучения языка программирования Kotlin
Рекомендации по разработке на Kotlin
Основы языка Kotlin
Типы данных и объявление переменных
Операторы и выражения в Kotlin
Циклы и управляющие конструкции
Объектно-ориентированное программирование в Kotlin
Синтаксис и пунктуация в Kotlin
Ключевые слова языка Kotlin
Встроенные функции и расширения Kotlin