Навчальний простір / Kotlin
Програмування мобільних застосунків

Android-проєкт зі списком, деталями та back stack

Навігація за ID зберігає предметну ідентичність.

Зміст матеріалу

Мета і потрібні знання

Створити двоекранний застосунок із навігацією за ID та перевірити повернення й зміну конфігурації. Потрібно знати List, data class, composable і route. Демонстрація показує список тем і деталі; самостійне завдання додає власну предметну модель та третій екран.

Підготовка середовища

Створіть Empty Activity Compose проєкт TopicLab з package com.example.topiclab, minSdk 24 або вище. Залиште узгоджені залежності шаблону. У app/build.gradle.kts усередині dependencies додайте implementation("androidx.navigation:navigation-compose:2.10.2"), версію з перевіреної документації Navigation. Виконайте Sync Now. Строкові routes цього прикладу не потребують Kotlin serialization plugin.

Перш ніж замінити код, запустіть шаблон на AVD. Якщо залежність потребує новішого compileSdk за повідомленням Gradle, використайте підтримуваний SDK через SDK Manager та узгоджений шаблон Android Studio; не знижуйте версію бібліотеки навмання. Створіть таблицю очікуваних переходів list → detail → list.

Повний MainActivity.kt

kotlin
package com.example.topiclab

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavType
import androidx.navigation.navArgument
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController

data class Topic(val id: Int, val title: String, val description: String)
private val topics = listOf(
    Topic(1, "Kotlin", "Типи й перевірка введення"),
    Topic(2, "Compose", "Стан та події UI")
)
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { MaterialTheme { Surface { TopicNavigation() } } }
    }
}
@Composable
fun TopicNavigation() {
    val nav = rememberNavController()
    NavHost(navController = nav, startDestination = "topics") {
        composable("topics") {
            Column(Modifier.fillMaxSize().padding(24.dp),
                   verticalArrangement = Arrangement.spacedBy(12.dp)) {
                Text("Навчальні теми")
                topics.forEach { topic ->
                    Button(onClick = { nav.navigate("topic/${topic.id}") {
                        launchSingleTop = true
                    } }) { Text(topic.title) }
                }
            }
        }
        composable("topic/{id}", arguments = listOf(
            navArgument("id") { type = NavType.IntType }
        )) { entry ->
            val id = entry.arguments?.getInt("id")
            val topic = topics.firstOrNull { it.id == id }
            Column(Modifier.fillMaxSize().padding(24.dp),
                   verticalArrangement = Arrangement.spacedBy(12.dp)) {
                Text(topic?.title ?: "Тему не знайдено")
                Text(topic?.description ?: "Поверніться до списку")
                Button(onClick = { nav.popBackStack() }) { Text("Назад") }
            }
        }
    }
}

Запустіть Run. Натискання Kotlin показує відповідні назву й опис, Back повертає список. FirstOrNull дає відсутність для невідомого ID, тому !! не потрібний. NavHost керує destination, а rememberNavController зберігає controller. ID передається як число; предметні дані залишаються в одному джерелі topics.

Покрокові перевірки

Перевірте обидві теми та кнопку назад, потім системне повернення Android. Поверніть пристрій на деталях і перевірте поточну destination. Додайте тимчасову навчальну кнопку route topic/999 та переконайтеся у стані відсутності; після перевірки приберіть її. Швидкі повторні натискання перевіряють launchSingleTop для верхньої destination, а не всі можливі дублікати історії.

Намалюйте граф routes і запишіть аргументи. Поясніть, чому передається ID, а не вся data class. Для великих списків замініть Column на LazyColumn зі стабільними keys. Це розвиток UI прикладу; правило ID і відсутності повинно залишитися тим самим.

Самостійне завдання

Створіть каталог навчальних матеріалів або обладнання з трьома destination: список, деталі й форма. Визначте стани форми, правило збереження й скасування. Передавайте мінімальні аргументи й підтримуйте один узгоджений власник даних. Власна форма та модель є основною самостійною частиною.

Складіть щонайменше сім сценаріїв: правильний ID, невідомий, повторний перехід, системний Back, кнопка Back, поворот і скасування редагування. Додатковий варіант — збереження невеликої чернетки через rememberSaveable. Поясніть, чи це достатньо для довгострокового збереження створеного матеріалу.

Помилки та налагодження

Unresolved NavHost вказує на import або залежність. Тип аргументу не збігається з route — перевірте navArgument. Копії даних різних екранів можуть розходитися після редагування. PopUpTo без аналізу може видалити потрібну історію. Відтворюйте збій із початкового списку й записуйте послідовність route.

Результат та контрольні питання

Подайте source project, граф, таблицю переходів і результати сценаріїв. Поясніть різницю ID та позиції у списку, scope controller і стан відсутності. Як перевірити process death окремо від повороту? Які дані слід завантажити заново після відновлення?

Перевірка маршруту та відсутнього об’єкта

Складіть таблицю для кожного destination: route, аргументи, джерело даних, доступні події та очікуваний шлях назад. У демонстрації список передає id теми. Деталі шукають відповідний об’єкт; якщо його немає, показують визначене повідомлення. Така відмова може виникнути через застаріле посилання або неправильний id, тому її потрібно опрацювати явно.

Перевірте послідовність список → перша тема → назад → друга тема. На кожному етапі звірте заголовок і кнопку повернення. Повторне натискання рядка не повинне створювати неочікувану історію; для власного сценарію визначте потрібну політику. Системна кнопка Back і кнопка екрана можуть викликати той самий навігаційний результат.

Для трьох екранів основного завдання намалюйте граф переходів перед кодом. Виберіть мінімальні аргументи для кожного маршруту й визначте їхню валідність. Якщо додаєте довільний текст у route, потрібно коректне кодування; простий стабільний id зменшує такі залежності. Не передавайте пароль або секрет у маршруті.

Якщо Gradle не знаходить navigation-compose, перевірте запис у dependencies, наявність google() серед репозиторіїв і результат sync. Missing import та unresolved route є окремими помилками коду. Не змінюйте всі версії навмання: звірте конкретне повідомлення сумісності з документацією бібліотеки. У звіті збережіть MainActivity, рядок доданої залежності, граф переходів та фактичні результати тестових маршрутів.

Окремий контрольний сценарій

Після повороту екрана перевірте, який destination відновився і чи заголовок відповідає його id. Не визначайте поточну тему окремою випадковою глобальною змінною: вона могла б суперечити маршруту. Для власного третього екрана запишіть сценарій повернення та дані, які мають залишитися. У звіті відділіть відновлення навігації від постійного збереження змісту: це різні механізми, що перевіряються різними сценаріями.

Схема процесу

Android-проєкт зі списком, деталями та back stackОберіть елемент, щоб побачити пояснення

Подія містить стабільний ID.

Самоперевірка

Перевірте розуміння
Чому пошук firstOrNull корисний для деталей?
Як обґрунтувати відповідь своїми словами?
Відсутній запис є визначеним станом UI, а не приводом розіменувати null.
Перед завершенням роботи

Підсумок

Навігація за ID зберігає предметну ідентичність. Стан відсутності, back stack та перевірка конфігурації роблять переходи передбачуваними. Третій екран потребує власного контракту стану й збереження.

Джерела

Як оформити та здати роботу →

Опрацювали матеріал?

Збережіть цей крок у своєму прогресі.

← Повернутися до дисципліни
© 2026 Анастасія Іскандарова-МалаЕлектронний навчальний посібник · ДДТУ

Пошук у посібнику

Спробуйте «C++», «RAII» або «бази даних».