我第一次在android中使用dagger2,并尝试使用与dagger2相同的结构来反映我的项目。google/iosched
. 但当我编译下面这个简单的项目时,它却报告了以下内容 MainActivityModule
不能在其中使用。
// MainApplication.kt
class MainApplication : DaggerApplication() {
...
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.factory().create(this)
}
...
}
// AppComponent.kt
@Singleton
@Component(
modules = [
AndroidSupportInjectionModule::class,
AppModule::class,
ActivityBindingModule::class,
ViewModelModule::class
]
)
interface AppComponent : AndroidInjector<MainApplication> {
@Component.Factory
interface Factory {
fun create(@BindsInstance application: MainApplication): AppComponent
}
}
// ActivityBindingModule.kt
@Module
@Suppress("UNUSED")
abstract class ActivityBindingModule {
@ActivityScoped
@ContributesAndroidInjector(
modules = [
// activity
MainActivityModule::class
]
)
internal abstract fun mainActivity(): MainActivity
}
// MainActivity.kt
class MainActivity : DaggerAppCompatActivity() {
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
@Inject lateinit var viewModel: MainActivityModule
override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.AppTheme)
super.onCreate(savedInstanceState)
viewModel = viewModelProvider(viewModelFactory)
}
...
}
// MainActivityModule.kt
@Module
@Suppress("UNUSED")
abstract class MainActivityModule {
@Binds
@IntoMap
@ViewModelKey(MainActivityViewModel::class)
internal abstract fun bindViewModel(viewModel: MainActivityViewModel): ViewModel
}
// MainActivityViewModel.kt
class MainActivityViewModel @Inject constructor(
) : ViewModel() {
}
下面的错误信息。
[Dagger/MissingBinding] com.example.app.di.MainActivityModule cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector<com.example.app.MainApplication> {
^
com.example.app.di.MainActivityModule is injected at
com.example.app.ui.MainActivity.viewModel
com.example.app.ui.MainActivity is injected at
注意 iosched 示例 MainActivity.kt:116 注入一个MainActivity查看模型:
private lateinit var viewModel: MainActivityViewModel
当你注入了一个MainActivity的时候模块:
@Inject lateinit var viewModel: MainActivityModule
有几个说明。
模块是用来配置Dagger的 你永远不需要注入或参考 模块 从您的ViewModels、Activity、Views或其他类。在所有情况下,您应该只与模块实例进行交互 如果 你有一个不是接口或抽象(开放)类的Module,而且它没有一个公共的无参数构造函数。
尽管你几乎不应该在你的图中注入模块,但Dagger会在你的图中注入 允许 你这样做 如果且仅如果 它们在你的图中被绑定。你应该这样理解错误信息。"com.example.app.di.MainActivityModule不能在没有@Provides-annotated方法的情况下被提供";因为你已经通过 @Inject
而Dagger不知道如何提供一个,它就会抛出这个编译时异常。
请注意,iosched的MainActivity.kt并没有将MainActivityViewModel标记为可注入的,它是手动创建实例。在第136行 就像你在这里发布的代码一样。要么你应该构造实例,要么Dagger应该构造实例,但不能同时构造。(Dagger 偶尔会对填充 @Inject
字段,但在这里你不需要这样做)。) 所以在任何情况下,你都可以放弃 @Inject
注释,小刀就不再担心了。