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
ViewModelmożna aktualizowaćMutableStateFlow(lub inny obserwowalny typ) z bieżącymUiState. - W
FragmentlubActivitysubskrybować zmianyUiStatei za pomocąwhenobsł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.