https://kotlinlang.org logo
#flow
Title
# flow
k

KotlinLeaner

03/05/2024, 12:01 PM
Hello, I have Events and I want to share same event again. So which flow is best for my use case
SharedFlow
? I created this class for navigating the screens based on response. This code is just basic example.
Copy code
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)
    }
}
Using above class inside the viewmodel
Copy code
class 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)
    }
}
How can I avoid initial value in this case?
Copy code
@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.
u

uli

03/08/2024, 9:24 AM
How about
StateFlow
? 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 be
k

KotlinLeaner

03/08/2024, 11:24 PM
Thanks for explanation, I got the point to use stateflow for my use case.