Dagger 2、Cicerone、Kotlin - 注入问题
Dagger 2, Cicerone, Kotlin - inject problem
此代码在 Java 中完美运行,但在 Kotlin
中存在未定义的问题
问题:
error: [Dagger/MissingBinding] ru.terrakok.cicerone.Router cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract void inject(@org.jetbrains.annotations.NotNull()
ru.terrakok.cicerone.Router is injected at
com.setname.dagger2ciceronelearning.presentation.main.MainActivity.mRouter
com.setname.dagger2ciceronelearning.presentation.main.MainActivity is injected at
com.setname.dagger2ciceronelearning.di.AppComponent.inject(com.setname.dagger2ciceronelearning.presentation.main.MainActivity)
AppComponent
@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
}
LearingApp
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()
}
}
正如一位非常聪明的人曾经说过的:You need to target the annotation at the field by using @field:Named.
您可以尝试使用自定义限定符:
@Qualifier
@Retention
annotation class RouterFirstLevel
那么你的模块:
@Provides
@Singleton
@RouterFirstLevel
fun provideFirstLevelRouter(): Router = firstLevelNavigation.router
和activity:
@Inject
@RouterFirstLevel
lateinit var mRouter: Router
P.S。不过我同意 jbarat,注释中的字段应该有帮助,尝试使用字符串而不是字符串常量,可能是某种类型不匹配
此代码在 Java 中完美运行,但在 Kotlin
中存在未定义的问题问题:
error: [Dagger/MissingBinding] ru.terrakok.cicerone.Router cannot be provided without an @Inject constructor or an @Provides-annotated method. public abstract void inject(@org.jetbrains.annotations.NotNull()
ru.terrakok.cicerone.Router is injected at com.setname.dagger2ciceronelearning.presentation.main.MainActivity.mRouter
com.setname.dagger2ciceronelearning.presentation.main.MainActivity is injected at com.setname.dagger2ciceronelearning.di.AppComponent.inject(com.setname.dagger2ciceronelearning.presentation.main.MainActivity)
AppComponent
@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
}
LearingApp
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()
}
}
正如一位非常聪明的人曾经说过的:You need to target the annotation at the field by using @field:Named.
您可以尝试使用自定义限定符:
@Qualifier
@Retention
annotation class RouterFirstLevel
那么你的模块:
@Provides
@Singleton
@RouterFirstLevel
fun provideFirstLevelRouter(): Router = firstLevelNavigation.router
和activity:
@Inject
@RouterFirstLevel
lateinit var mRouter: Router
P.S。不过我同意 jbarat,注释中的字段应该有帮助,尝试使用字符串而不是字符串常量,可能是某种类型不匹配