【问题标题】:Dagger 2, Cicerone, Kotlin - inject problemDagger 2, Cicerone, Kotlin - 注入问题
【发布时间】:2019-10-27 06:28:45
【问题描述】:

这段代码在 Java 中完美运行,但在 Kotlin 中有一个未定义的问题

问题

错误:[Dagger/MissingBinding] ru.terrakok.cicerone.Router 不能在没有@Inject 构造函数或@Provides-annotated 方法的情况下提供。 公共抽象无效注入(@org.jetbrains.annotations.NotNull()

ru.terrakok.cicerone.Router 注入于 com.setname.dagger2ciceronelearning.presentation.main.MainActivity.mRouter

com.setname.dagger2ciceronelearning.presentation.main.MainActivity 注入于 com.setname.dagger2ciceronelearning.di.AppComponent.inject(com.setname.dagger2ciceronelearning.presentation.main.MainActivity)

应用组件

@Singleton
@Component(modules = arrayOf(NavigationModule::class))
interface AppComponent {

    fun inject(mainActivity: MainActivity)
    fun inject(fragmentOne: FragmentOne)
    fun inject(fragmentTwo: FragmentTwo)

}

导航模块

@Module
class NavigationModule {

    private val firstLevelNavigation: Cicerone<Router> = Cicerone.create()
    private val secondLevelNavigation: Cicerone<Router> = Cicerone.create()

    @Provides
    @Singleton
    @Named(Navigation.ROUTER_FIRST_LEVEL)
    fun provideFirstLevelRouter(): Router = firstLevelNavigation.router

    @Provides
    @Singleton
    @Named(Navigation.ROUTER_SECOND_LEVEL)
    fun provideSecondLevelRouter(): Router = secondLevelNavigation.router

    @Provides
    @Singleton
    @Named(Navigation.NAV_HOLDER_FIRST_LEVEL)
    fun provideFirstLevelNavigatorHolder(): NavigatorHolder = firstLevelNavigation.navigatorHolder


    @Provides
    @Singleton
    @Named(Navigation.NAV_HOLDER_SECOND_LEVEL)
    fun provideSecondLevelNavigationHolder(): NavigatorHolder = secondLevelNavigation.navigatorHolder

}

学习应用

class LearningApp : Application() {

    companion object {

        lateinit var appComponent: AppComponent

    }

    override fun onCreate() {
        super.onCreate()
        appComponent = DaggerAppComponent
            .builder()
            .build()
    }

}

MainActivity

class MainActivity : AppCompatActivity() {

    @Inject
    @Named(Navigation.ROUTER_FIRST_LEVEL)
    lateinit var mRouter: Router

    @Inject
    @Named(Navigation.NAV_HOLDER_FIRST_LEVEL)
    lateinit var mNavigatorHolder: NavigatorHolder

    private lateinit var mNavigator:Navigator

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        LearningApp.appComponent.inject(this)

        mNavigator = SupportAppNavigator(this, R.id.main_container)

        mRouter.newRootScreen(Screens.FragmentOneScreen())

    }

    override fun onResume() {
        super.onResume()
        mNavigatorHolder.setNavigator(mNavigator)
    }

    override fun onPause() {
        mNavigatorHolder.removeNavigator()
        super.onPause()
    }

}

【问题讨论】:

    标签: android kotlin dependency-injection dagger-2


    【解决方案1】:

    正如一位非常聪明的人曾经说过的那样:You need to target the annotation at the field by using @field:Named.

    【讨论】:

    • 但几年后,同样的智者说:«‎我猜对了一半。您需要使用@field:Named 将注释定位在字段上。但这并没有解决他的问题。»‎
    • 但几秒钟后他说:«‎不,这会解决他的问题。»‎
    【解决方案2】:

    您可以尝试使用自定义限定符:

    @Qualifier
    @Retention
    annotation class RouterFirstLevel
    

    然后你的模块:

    @Provides
    @Singleton
    @RouterFirstLevel
    fun provideFirstLevelRouter(): Router = firstLevelNavigation.router
    

    和活动:

    @Inject
    @RouterFirstLevel
    lateinit var mRouter: Router
    

    附:不过我同意 jbarat,注释中的字段应该有帮助,尝试使用字符串而不是字符串常量,可能是某些类型不匹配

    【讨论】:

      猜你喜欢
      • 2018-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-30
      相关资源
      最近更新 更多