androidx.navigation.NavController 是否可以使用 DI

Is it possible to use DI with the androidx.navigation.NavController

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

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

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

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

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

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

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

我不明白你为什么要注入 NavController 当有方法供你找到它时,我也会担心使用依赖注入,因为持有对 [= 的引用15=].

鉴于您正在使用 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)
}

然后你可以简单地在片段中使用:

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

我已经在

中回答了这个问题

简而言之,

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