【问题标题】:Is it possible to use DI with the androidx.navigation.NavController是否可以将 DI 与 androidx.navigation.NavController 一起使用
【发布时间】:2020-02-05 00:53:32
【问题描述】:

所以,这个标题反映了这个问题。 要获取导航控制器 (androidx.navigation.NavController) 上的链接,我们通常使用以下代码:

NavController navController = Navigation.findNavController(this, R.id.nav_host_frag);

是否可以使用Dagger2 框架注入 NavController? (findNavController 需要活动或视图参考) 也许这是一个愚蠢的问题,没有人注入androidx.navigation.NavController,但尽管如此,我还是决定在我的假设中提出这个问题。先谢谢了

【问题讨论】:

    标签: android dependency-injection dagger-2 android-architecture-components androidx


    【解决方案1】:

    我不明白你为什么要注入 NavController,因为有方法可以找到它,而且由于持有对 Activity 的引用,我也会担心使用依赖注入。

    鉴于您正在使用Activity,您通常可以使用以下方法找到控制器:

    private val navController: NavController by lazy { findNavController(R.id.main_container) }
    

    现在,如果我们查看 findNavController() 方法的源代码,您会注意到它使用了扩展函数和 Navigation.findNavController(this, viewId)

    /**
     * Find a [NavController] given the id of a View and its containing
     * [Activity].
     *
     * Calling this on a View that is not a [NavHost] or within a [NavHost]
     * will result in an [IllegalStateException]
     */
    fun Activity.findNavController(@IdRes viewId: Int): NavController =
            Navigation.findNavController(this, viewId)
    

    我要做的唯一补充就是创建另一个扩展函数以方便从Fragment 导航。

    fun Fragment.navigate(resId: Int, bundle: Bundle? = null) {
        NavHostFragment.findNavController(this).navigate(resId, bundle)
    }
    

    那么你可以简单地在 Fragment 中使用:

    navigate(
        R.id.action_fragmentA_to_FragmentB,
        bundleOf(Global.CAN_NAVIGATE_BACK to false)
    )
    

    【讨论】:

    • 我猜杰克琼斯问的原因是因为他想从他的视图模型中启动导航。我有类似的需要,想从状态机内部控制导航......
    • @OveStoerholt,在这种情况下,您可以使用命令设计模式来封装动作,您需要对原生视图的引用,因此您必须将责任委托给片段或活动.
    • 你永远不应该在你的视图模型中持有对视图的引用。它超越了关注点的整体分离……您应该以不同的方式考虑导航。您的视图模型上应该有一个可观察的对象来控制您的 UI。您只需要更新您的 observable 并在您的视图中收听它,从而控制 UI
    【解决方案2】:

    为什么这不起作用?您可以像任何其他对象一样将其添加到组件中

    • 通过 Component.Builder 通过 @BindsInstance 或带有参数的模块
    • 通过从 @Provides 带注释的方法返回它

    使用@Provides 注释方法,您需要在组件中也有可用的活动或视图。根据您使用 Dagger 的方式,您通常可以使用特定的 Activity,因此您可以使用它,例如对于 MyActivityComponentMyActivity 你可以简单地在一个模块中返回它

    @Provides
    NavController bindController(MyActivity activity) {
      Navigation.findNavController(this, R.id.nav_host_frag)
    }
    

    【讨论】:

    【解决方案3】:

    我已经在https://stackoverflow.com/a/60061872/789110回答了这个问题

    总之,

    • 通过常用的匕首方式提供NavController,例如:
       @Provides
        fun providesNavController(activity: MainActivity): NavController {
            return activity.supportFragmentManager.findFragmentById(R.id.main_content).findNavController()
        }
    
    • onAttach注入NavController
    • lazily注入NavController 以避免Android 重新创建Activity 和何时可以检索NavController 之间的竞争条件:
        @Inject
        lateinit var navController: Provider<NavController>
    

    【讨论】:

      猜你喜欢
      • 2021-11-12
      • 2016-04-01
      • 2011-01-20
      • 2018-08-11
      • 2021-08-05
      • 2019-03-18
      • 2014-03-15
      • 2021-03-31
      • 2020-12-22
      相关资源
      最近更新 更多