Kotlin Academy · Lekcja

Modelowanie stanu interfejsu za pomocą klas sealed

Zastosuj klasy sealed do reprezentowania stanów interfejsu Loading, Success i Error.

Lekcja 3 z 413 kroki

Modelowanie stanu interfejsu za pomocą klas sealed to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Problem ze stanem interfejsu użytkownika

Ekrany interfejsu użytkownika mają wiele stanów: ładowanie, wyświetlanie danych, wyświetlanie błędu lub pusty stan. Zarządzanie nimi za pomocą wartości logicznych (isLoading, hasError) jest podatne na błędy. Klasy sealed rozwiązują ten problem.

Klasyczne piekło wartości logicznych

Używanie oddzielnych wartości logicznych prowadzi do stanów niemożliwych.
// Fragile: isLoading=true AND hasError=true is invalid
var isLoading = false
var hasError = false
var data: List<Item>? = null
// 8 combinations, most of which are invalid!

Stan sealed: tylko poprawne stany

Klasa sealed sprawia, że niepoprawnych stanów nie da się reprezentować.
sealed class UiState<out T>
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String, val retryable: Boolean = true) : UiState<Nothing>()
object Empty : UiState<Nothing>()

Renderowanie na podstawie stanu

Należy używać when, aby renderować właściwy interfejs użytkownika dla każdego stanu.
fun render(state: UiState<List<Item>>) = when (state) {
    Loading -> showProgressBar()
    is Success -> showItems(state.data)
    is Error -> showError(state.message, state.retryable)
    Empty -> showEmptyView()
}

Emitowanie stanów przez ViewModel

ViewModel emituje stany sealed za pośrednictwem StateFlow.
class ItemViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState<List<Item>>>(Loading)
    val state: StateFlow<UiState<List<Item>>> = _state

    fun loadItems() = viewModelScope.launch {
        _state.value = Loading
        _state.value = try {
            Success(repository.getItems())
        } catch (e: Exception) {
            Error(e.message ?: "Unknown error")
        }
    }
}

Komponowanie stanów z zawartością

Należy używać generycznych stanów sealed do obsługi dowolnego typu danych.
fun <T> loading(): UiState<T> = Loading
fun <T> success(data: T): UiState<T> = Success(data)
fun <T> error(msg: String): UiState<T> = Error(msg)

Przykład stanu paginacji

Klasy sealed w naturalny sposób modelują stany listy podzielonej na strony.
sealed class PageState
object Idle : PageState()
object FirstLoad : PageState()
data class Content(val items: List<Item>, val hasMore: Boolean) : PageState()
data class LoadingMore(val items: List<Item>) : PageState()
data class Error(val items: List<Item>?, val msg: String) : PageState()

Przekształcanie stanu

Stany pomyślne można mapować bez modyfikowania pozostałych przypadków.
fun <T, R> UiState<T>.mapData(transform: (T) -> R): UiState<R> = when (this) {
    is Success -> Success(transform(data))
    is Error -> this
    Loading -> Loading
    Empty -> Empty
}

Testowanie za pomocą stanów sealed

Stany łatwo testować — wystarczy sprawdzić, który wariant został wyemitowany.
@Test
fun testLoadingState() {
    viewModel.loadItems()
    assertEquals(Loading, viewModel.state.value)
}
@Test
fun testSuccessState() {
    viewModel.setData(listOf(item))
    assert(viewModel.state.value is Success)
}

Połączony stan a wiele przepływów

Pojedynczy przepływ stanu sealed jest przejrzystszy niż wiele oddzielnych przepływów, które muszą pozostać zsynchronizowane.
// Fragile: two flows must stay in sync
val loading = MutableStateFlow(false)
val error = MutableStateFlow<String?>(null)

// Clean: one sealed state
val state = MutableStateFlow<UiState<List<Item>>>(Loading)

Dodawanie metadanych do stanów

Podtypy sealed mogą przechowywać odpowiednie metadane.
data class Error(
    val message: String,
    val code: Int = 0,
    val retryable: Boolean = true,
    val timestamp: Long = System.currentTimeMillis()
) : UiState<Nothing>()

Szybkie sprawdzenie

Jaki kluczowy problem rozwiązuje modelowanie stanu interfejsu użytkownika za pomocą klas sealed?

Podsumowanie

Modeluj stan interfejsu użytkownika za pomocą klas sealed: Loading, Success(data), Error(message), Empty. Używaj when do renderowania każdego przypadku. Jeden StateFlow z typem sealed jest lepszy niż wiele flag logicznych. Dalej: zagnieżdżanie hierarchii sealed!
Bezpłatny start

Ucz się Kotlin dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
51
Lekcje
203

Często zadawane pytania

Czy lekcja „Modelowanie stanu interfejsu za pomocą klas sealed” jest bezpłatna?

Tak — pełny tekst „Modelowanie stanu interfejsu za pomocą klas sealed” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Modelowanie stanu interfejsu za pomocą klas sealed”?

Zastosuj klasy sealed do reprezentowania stanów interfejsu Loading, Success i Error. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Modelowanie stanu interfejsu za pomocą klas sealed”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. sealed class a sealed interface: kiedy używać każdej z nich
  2. Kompletne when z hierarchiami sealed
  3. Modelowanie stanu interfejsu za pomocą klas sealed
  4. Zagnieżdżanie i łączenie hierarchii sealed
← Powrót do Kotlin Academy