Sobes.tech
Middle

Jak za pomocą klas sealed można zaimplementować różne stany w aplikacji Android?

sobes.tech AI

Odpowiedź od AI

Zamknięte klasy są idealne do modelowania końcowego zestawu stanów. Każdy stan podrzędny może zawierać własne unikalne dane.

Przykład:

sealed class UiState {
    object Loading : UiState() // Stan ładowania bez danych
    data class Success(val data: List<Item>) : UiState() // Stan sukcesu z otrzymanymi danymi
    data class Error(val message: String) : UiState() // Stan błędu z wiadomością

    object Idle : UiState() // Stan początkowy lub neutralny
}

Zastosowanie:

  • W ViewModel można aktualizować MutableStateFlow (lub inny obserwowalny typ) z bieżącym UiState.
  • W Fragment lub Activity subskrybować zmiany UiState i za pomocą when obsługiwać każdy możliwy stan, odpowiednio aktualizując UI.
// W ViewModel
class MyViewModel : ViewModel() {
    private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
    val uiState: StateFlow<UiState> = _uiState.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _uiState.value = UiState.Loading
            try {
                val result = fetchData() // Twoja funkcja pobierania danych
                _uiState.value = UiState.Success(result)
            } catch (e: Exception) {
                _uiState.value = UiState.Error(e.message ?: "Nieznany błąd")
            }
        }
    }
}
// W Fragment/Activity (używając Compose)
@Composable
fun MyScreen(viewModel: MyViewModel = viewModel()) {
    val uiState by viewModel.uiState.collectAsState()

    when (uiState) {
        UiState.Idle -> { /* Wyświetl ekran początkowy */ }
        UiState.Loading -> { /* Wyświetl wskaźnik ładowania */ }
        is UiState.Success -> {
            val data = (uiState as UiState.Success).data
            // Wyświetl dane
        }
        is UiState.Error -> {
            val errorMessage = (uiState as UiState.Error).message
            // Wyświetl komunikat o błędzie
        }
    }
}

Zalety:

  • Wyjątkowa kontrola: Kompilator wymaga obsługi wszystkich podklas klasy zamkniętej w when. Zapobiega to pominięciom i zwiększa niezawodność kodu.
  • Jasne modelowanie stanów: Wyraźnie określa wszystkie możliwe stany komponentu UI.
  • Bezpieczeństwo typów: Każdy stan ma własne dane, do których dostęp jest bezpieczny, bez konieczności rzutowania.
  • Lepsza czytelność: Kod korzystający z klas zamkniętych dla stanów jest bardziej zrozumiały i łatwiejszy w utrzymaniu.

To podejście jest szczególnie przydatne z Flow i Compose, ale dobrze działa także z LiveData i View Binding.