Waheed KhAn
03/27/2025, 9:51 AMdata class
as a state holder in Jetpack Compose instead of a sealed class
or sealed interface
?Pablichjenkov
03/27/2025, 12:31 PMView State
and View Data
You use the sealed class for View State and data class for View Data
Like bellow:
sealed class MyViewState {
class Initial(viewData: ViewInitialData) : MyViewState ()
class FetchingRemoteData(viewData: LoadingAnimationData) : ...
class Content(contentData: ContentData) : ...
class Error(errorData: ErrorData) : ...
class RetryingFromError(loadingAnimData: LoadingAnimData)
}
data class ViewInitialData ...
data class LoadingAnimationData ...
data class ContentData
data class ErrorData
Zach Klippenstein (he/him) [MOD]
03/27/2025, 3:23 PMWaheed KhAn
03/28/2025, 6:32 AM@Immutable
data class HomeUIState(
val isLoading: Boolean = false,
val userRole: String = "",
val firstName: String = "",
val lastName: String = "",
val profileImage: String = "",
val balance: Double = 0.0,
val appVersion: String = "",
val currentLanguage: String = "en".uppercase(),
val currentTheme: String = THEME_LIGHT,
val isRefreshing: Boolean = false,
val filteredTClasses: List<TClassComm> = emptyList(),
val filteredMaterials: List<MaterialComm> = emptyList(),
val navigationPathFlow: List<String> = listOf("Top Level")
)
this is my homeUiState class is this approach is fine to avoid/skip unnecessary recomposition?
Waheed KhAn
03/28/2025, 6:53 AMfun onPullToRefreshTrigger() {
viewModelScope.launch {
navigationRepo.getAllRelevantNavigationTClasses().collect { tClass ->
val newState = when (tClass) {
is DataState.Loading -> _homeUIState.value.copy(isRefreshing = tClass.isLoading)
is DataState.Data -> {
_allTClasses.value = tClass.data
_homeUIState.value.copy(
filteredTClasses = _allTClasses.value.filter { it.parentTClassId == null },
filteredMaterials = emptyList(),
navigationPathFlow = listOf("Top Level")
)
}
is DataState.Messages -> {
<http://LocalMessageEvent.post|LocalMessageEvent.post>(BaseLocalMessagesEvent.LocalMessages(tClass.messages))
_homeUIState.value
}
}
_homeUIState.value = newState // Single state update
}
}
}
Waheed KhAn
03/28/2025, 6:54 AMWaheed KhAn
03/28/2025, 6:56 AMWaheed KhAn
03/28/2025, 7:05 AMTLoadBaseScreen(isLoading = homeUIState.isLoading, topBar = {
CenterAlignedTopAppBar(
title = {
// title
},
navigationIcon = {
Icon(
painter = painterResource(R.drawable.baseline_menu_24),
contentDescription = stringResource(<http://R.string.menu|R.string.menu>), // Accessibility improvement
modifier = Modifier
.padding(start = 12.dp)
.size(24.dp) // Ensuring proper touch target
.clickable {
coroutineScope.launch {
if (drawerState.isClosed) {
drawerState.open()
}
}
}
)
},
actions = {
// action
},
modifier = modifier.shadow(
elevation = 4.dp,
spotColor = MaterialTheme.colorScheme.primary, // Theme-based color instead of hardcoded Orange
ambientColor = MaterialTheme.colorScheme.primary
)
)
}, content = { paddingValues ->
//rest of the content of screen
}
Zach Klippenstein (he/him) [MOD]
03/28/2025, 8:03 AMWaheed KhAn
03/28/2025, 9:42 AM