a

    allan.conda

    1 year ago
    I’ve been migrating our code to compose-navigation. We’re using MVVM but the navigation does not go through the ViewModel and we delegate it directly to the composable up to the navigation graph. For user interaction that does some processing before navigation (such as login) we expose a
    suspend fun
    which returns the operation’s result and navigate accordingly. Works fine so far, and now I encountered a new use-case integrating with non-Kotlin code. I use CameraX ImageCapture use case with takes a listener for successful capture, I can’t use suspend fun to wait for the result. So now I’m looking for options. I wonder if we could represent capture events from the ViewModel, and I remember discussions on SingleLiveEvents and we now prefer representing state instead of events in Compose. For example we now use state for snackbar or dialog visibility instead of SingleLiveEvent. I’m not sure how to do this for navigation events. I’ve seen articles suggesting
    StateFlow
    ,
    SharedFlow
    ,
    Channel
    for navigation events, but I’m curious what the Compose team thinks. I haven’t found an official example where the navigation is handled within the ViewModel, is it deliberate that we want to decouple ViewModels from the Views’ navigations completely (no mention of “navigation” within a ViewModel)? We’re also having internal discussions how to handle navigation in our Compose+MVVM architecture and we’re split on what we need to do about whether we should call the navigation lambda directly on user event (like onClick) or whether we should keep our Composables pure&passive.
    Basically, in general, we’re split on whether we should do something like this
    Screen(
        state = viewModel.state,
        toLogin = actions.toLogin,
    )
    Or this
    viewModel.navigateToLoginEvent.observe {
        actions.toLogin()
    }
    Screen(
        onLoginButtonClick = viewModel.onLoginButtonClick,
    )
    We are doing the former currently, but we’re not sure we’re following MVVM correctly by doing this. Technically our Composables know when to navigate, instead of simply delegating the user event somewhere else such as into the ViewModel.
    Albert Chang

    Albert Chang

    1 year ago
    Jetnews used to use ViewModel for navigation.
    By the way you can use
    suspendCancellableCoroutine
    to convert a callback into a suspend function.