mvvmandroid-jetpack-composeandroid-viewmodeldagger-hiltandroid-jetpack-compose-scaffold

How do I pass a function from a ViewModel to my scaffold's floating action button in Jetpack Compose?


I'm building an Android app using purely Jetpack Compose. My entire application is wrapped under one scaffold, and has a ViewModel for each "screen" (which are composables) in my app. Because of that, I have some conditional statements in my scaffold to determine the floating action button (FAB) based on the route. However, one of the FABs needs access to a function in a ViewModel, which is only created when I navigate to the route that holds that composable, and I'm at a loss on the best way to give the FAB access to that viewmodel function.

Take the following example (based off my code), and note the FAB for the route "route3".

@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            MyApp()
        }
    }

    @Composable
    fun MyApp() {
        val navController = rememberNavController()
        val backstackEntry = navController.currentBackStackEntryAsState()
        val scaffoldState = rememberScaffoldState()

        Surface(color = MaterialTheme.colors.background) {
            Scaffold(
                topBar = { ... },
                bottomBar = { ... },
                floatingActionButton = {
                    when (backstackEntry.value?.destination?.route) {
                        "route2" -> FAB2(navController)
                        "route3" -> FAB3(navController) // Needs to access function from viewModel3
                    }
                },
                scaffoldState = scaffoldState,
            ) {
                MyNavHost(navController, scaffoldState)
            }
        }
    }

    @Composable
    fun MyNavHost(navController: NavHostController, scaffoldState: ScaffoldState) {
        NavHost(
            navController = navController,
            startDestination = "route1"
        ) {
            composable("route1") { Destination1() }
            composable("route2") { Destination2() }
            composable("route3") { Destination3() }
        }
    }

    @Composable
    fun Destination1() { ...}

    @Composable
    fun Destination2() { ... }

    @Composable
    fun Destination3() {
        val viewModel3: CustomViewModel = hiltViewModel()
        Screen3(viewModel3)
    }

}

So my main question is, if the FAB3 variable needs to access a function from viewModel3, how would I go about doing it?


Solution

  • I decided to just switch over to using a scaffold for every screen.

    Honestly, this makes managing routes a lot easier, because in the single scaffold scenario, it was getting difficult managing all of the possible routes for things like the TopBar and FAB in large when() blocks.

    But if anyone has a solution to the original question that would be appreciated!