KotlinLeaner
03/05/2024, 12:01 PMSharedFlow
? I created this class for navigating the screens based on response. This code is just basic example.
class Navigator : NavigationHandler {
private val _destination: MutableSharedFlow<ScreenName> = MutableSharedFlow(
replay = 1,
onBufferOverflow = BufferOverflow.DROP_OLDEST
)
override val destination: SharedFlow<ScreenName> = _destination.asSharedFlow()
override fun navigate(navigationDestination: ScreenName) {
_destination.tryEmit(navigationDestination)
}
}
KotlinLeaner
03/05/2024, 12:02 PMclass MainViewModel(
private val navigationHandler: NavigationHandler
) : ViewModel() {
val currentDestination: Flow<NavigationDestination> =
navigationHandler.destination.shareIn(
viewModelScope,
SharingStarted.WhileSubscribed(),
)
fun navigateToDeviceSelection(isValid: Boolean) {
val destination = if (isValid) {
ScreenName.ScreenOne
} else {
ScreenName.ScreenTwo
}
println(">> destination ${destination.route}")
navigationHandler.navigate(destination)
}
}
KotlinLeaner
03/05/2024, 12:03 PM@Composable
fun NavigationScreen(viewModel: MainViewModel = koinViewModel()) {
val destination by viewModel.currentDestination.collectAsState(initial = ScreenName.ScreenOne)
LaunchedEffect(viewModel, destination) {
viewModel.navigateToDeviceSelection(false)
}
LaunchedEffect(key1 = destination) {
Log.e(">> destination", destination.route)
}
Column {
Text(text = destination.route, fontSize = 20.sp)
}
}
When I run the code it always print first ScreenOne
then move to other condition like ScreenTwo
according to condition used inside navigateToDeviceSelection
function called. I just give me initial
by default because collectAsState
need that. I am using SharedFlow
because I want to trigger same event repeatedly. Above code is just example of 2 events but actually is more than that.
My main expected output will be to print first according to navigateToDeviceSelection
logic not by default value which I provided by collectAsState
. I don't want to use null
because this example is very basic and I need to add more events in here.uli
03/08/2024, 9:24 AMStateFlow
? I think that has a collectAsState
without default value, as it always has a value
.
The main issue seems to be, that flows are in general asynchronous, but UI needs a value immediately. Even for StateFlows you have to provide an initial state which will then later be replaced by your calculated value.
So wether State- or SharedFlow, you can either
• introduce an `ScreenName.UnInitialized`(or null
) where your UI has to somehow wait for the next emission
• Or set the default/initial value not from a hard coded value but call your calculation logic to find our what the initial state should beKotlinLeaner
03/08/2024, 11:24 PM