This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| val viewEffect = uiState.map { it.effect } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sealed interface UserProfileEffect { | |
| data class ShowError(val message: String) : UserProfileEffect | |
| data object NavigateToLogin : UserProfileEffect | |
| } | |
| data class UserProfileUiState( | |
| val isLoading: Boolean = false, | |
| val user: User? = null, | |
| val effect: UserProfileEffect? = null, | |
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Composable | |
| fun UserProfileScreen( | |
| viewModel: UserProfileViewModel = hiltViewModel() | |
| ) { | |
| val uiState by viewModel.uiState.collectAsStateWithLifecycle() | |
| // Handle effects | |
| LaunchedEffect(uiState.errorToShow) { | |
| uiState.errorToShow?.let { errorToShow -> | |
| showErrorDialog(errorToShow) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| data class UserProfileUiState( | |
| val isLoading: Boolean = false, | |
| val user: User? = null, | |
| val errorToShow: String? = null | |
| ) | |
| class UserProfileViewModel( | |
| private val userRepository: UserRepository | |
| ) : ViewModel() { | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SharedFlow without replay - loses events immediately | |
| private val _sharedFlowEvents = MutableSharedFlow<UIEvent>() | |
| viewModelScope.launch { // Already uses Dispatchers.Main.immediate | |
| delay(3000) // User goes to background | |
| _sharedFlowEvents.emit(UIEvent.Navigate) // LOST - no active collectors | |
| } | |
| // Channel - buffers events even without collectors | |
| private val _channelEvents = Channel<UIEvent>() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Composable | |
| fun UserProfileScreen( | |
| viewModel: UserProfileViewModel = hiltViewModel() | |
| ) { | |
| val lifecycleOwner = LocalLifecycleOwner.current | |
| LaunchedEffect(viewModel.events, lifecycleOwner) { | |
| viewModel.events.flowWithLifecycle(lifecycleOwner.lifecycle) | |
| .onEach { | |
| when (event) { |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sealed class UIEvent { | |
| object NavigateToLogin : UIEvent() | |
| data class ShowError(val error: String) : UIEvent() | |
| } | |
| class UserProfileViewModel( | |
| private val userRepository: UserRepository | |
| ) : ViewModel() { | |
| private val _events = Channel<UIEvent>() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class NoConsumptionTrackingViewModel : ViewModel() { | |
| private val _events = MutableSharedFlow<UIEvent>(replay = 1) | |
| val events = _events.asSharedFlow() | |
| fun showImportantDialog() { | |
| viewModelScope.launch { | |
| _events.emit(UIEvent.ShowCriticalDialog) | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Composable | |
| fun UserProfileScreen( | |
| viewModel: UserProfileViewModel = hiltViewModel() | |
| ) { | |
| val navController = LocalNavController.current | |
| val events by viewModel.events.collectAsStateWithLifecycle(initialValue = null) | |
| // Handle events when they change | |
| LaunchedEffect(events) { | |
| events?.let { event -> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| sealed class UIEvent { | |
| object NavigateToLogin : UIEvent() | |
| data class ShowError(val error: String) : UIEvent() | |
| } | |
| class UserProfileViewModel( | |
| private val userRepository: UserRepository | |
| ) : ViewModel() { | |
| // UI state management (normal StateFlow usage) |