Jetpack 编写如何集中 navController 并注入它

Jon*_*vin 1 kotlin koin android-jetpack-compose jetpack-compose-navigation

目前,我NavGraphs的应用程序中有两个,一个用于身份验证路由,例如登录和注册,另一个用于登录时的家庭路由。
当前,当我想使用它时,我需要navController在每个可组合项中将其作为参数传递。这绝对是不可扩展的,所以我想知道是否可以使其可注入,以便我可以通过 DI 框架(如Koin. 我目前正在Koin我的应用程序中使用,所以如果我可以使用它的依赖注入工具,将 anavController作为singleton.

当前导航设置

我目前在navController内部创建MainActifity

class MainActivity : AppCompatActivity() {
    private lateinit var navController: NavHostController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        startKoin {
            androidLogger(if (BuildConfig.DEBUG) Level.ERROR else Level.NONE)
            androidContext(this@MainActivity)
            modules(listOf(networkModule, viewModelModule, interactorsModule))
        }

        setContent {
            navController = rememberAnimatedNavController()
            SetupNavGraph(navController = navController)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将它传递到NavHost保存两个的NavGraphs

fun SetupNavGraph(
    navController: NavHostController
) {
    AnimatedNavHost(
        navController = navController,
        startDestination = AUTH_GRAPH_ROUTE,
        route = ROOT_GRAPH_ROUTE
    ) {
        homeNavGraph(navController = navController)
        authNavGraph(navController = navController)
    }
}
Run Code Online (Sandbox Code Playgroud)

以下是我的NavGraph所有身份验证路线。我还传递了NavController作为参数,以便我可以在屏幕内使用它。

fun NavGraphBuilder.authNavGraph(
    navController: NavController
) {
    navigation(
        startDestination = Screen.Login.route,
        route = AUTH_GRAPH_ROUTE
    ) {
        composable(
            Screen.Login.route,
        ) {
            val loginViewModel: LoginViewModel = getViewModel()

            LoginScreen(
                navController = navController,
                state = loginViewModel.state.value,
                onTriggerEvent = loginViewModel::onTriggerEvent
            )
        }
        composable(
            Screen.Register.route,
        ) {
            val registerViewModel: RegisterViewModel = getViewModel()
            RegisterScreen(
                navController = navController,
                state = registerViewModel.state.value,
                onTriggerEvent = registerViewModel::onTriggerEvent
            )
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

登录后的所有页面NavGraph与我的身份验证页面类似,因此不值得显示。

navController如果我可以通过 Koin 创建一个as a,那就太酷了,single但这是不可能的,因为rememberNavController函数只能在可组合项内部调用。

有什么解决方案可以解决将 传递navController到每个嵌套可组合项中的问题吗?

Phi*_*hov 6

为了方便测试/预览,建议仅传递处理程序而不是导航控制器本身,并SetupNavGraph在调用处理程序时在内部执行所有实际导航。更多信息可以在这里找到。

如果它不适合您,您可以创建自己的组合本地,如下所示:

val LocalNavController = compositionLocalOf<NavHostController> {
    error("No LocalNavController provided")
}
Run Code Online (Sandbox Code Playgroud)

提供CompositionLocalProvider

setContent {
    CompositionLocalProvider(LocalNavController provides rememberAnimatedNavController()) {
        SetupNavGraph()
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在任何可组合项中CompositionLocalProvider,您都可以使用 来获取导航控制器LocalNavController.current