您好我是dagger 2的新手,并尝试在我的MyActivity类中注入一个sharedPreference实例:
class MyApplication : Application() {
companion object {
@JvmStatic lateinit var applicationComponent : ApplicationComponent
}
override fun onCreate() {
super.onCreate()
applicationComponent = DaggerApplicationComponent.builder().androidModule(AndroidModule(this)).build()
}
}
这是组件和模块
@Singleton
@Component(modules = arrayOf(AndroidModule::class))
interface ApplicationComponent {
fun inject(mainActivity: MainActivity)
}
@Module
class AndroidModule (private val application: Application){
@Provides
@Singleton
fun provideApplicationContext() : Context = application
@Provides
@Singleton
fun provideSharedPreference() : SharedPreferences = application.getSharedPreferences("shared pref", Context.MODE_PRIVATE)
}
class MainActivity: Activity{
@Inject
internal lateinit var sharedPreference: SharedPreferences
@Inject
internal lateinit var MainScreenPresenter: MainScreenContract.Presenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_Screen)
MyApplication.applicationComponent.inject(this)
sharedPreference.toString()
initiateViews()
}
}
我收到以下错误:
Error:(7, 1) error: android.content.SharedPreferences cannot be provided without an @Provides- or @Produces-annotated method.
答案 0 :(得分:5)
你做得有点不对劲。首先,现在有dagger-android有助于解决组件(如活动)不应该知道注射如何发生的问题的原理问题。
你可以在这里阅读:https://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe
只是为了确保dagger依赖项在Android项目中:
android {
kapt {
generateStubs = true
}
}
compile "com.google.dagger:dagger:2.13"
compile "com.google.dagger:dagger-android:2.13"
compile "com.google.dagger:dagger-android-support:2.13"
kapt "com.google.dagger:dagger-compiler:2.13"
kapt "com.google.dagger:dagger-android-processor:2.13"
您的错误在于您没有告诉您的图表您想要注入MainActivity。以最佳方式为MainActivity创建Subcomponent
,将其与另一个MainActivity模块连接,该模块具有要注入MainActivity的注入,在AppComponent中设置与子组件的连接,而不是在MainAcitivy onCreate()中设置方法注入您的依赖图。但是使用dagger-android一切都更容易。
以下是代码:
@Singleton
@Component(modules = [
AndroidSupportInjectionModule::class,
ActivityBindingModule::class,
AppModule::class
])
interface AppComponent : AndroidInjector<DaggerApplication> {
fun inject(application: MyApplication)
override fun inject(instance: DaggerApplication)
@Component.Builder
interface Builder {
@BindsInstance fun application(application: MyApplication): Builder
fun build(): AppComponent
}
}
AndroidSupportInjectionModule.class :这来自dagger.android.support库。它还为我们的模块提供了Android组件(Activities / Fragments / Services / BroadcastReceiver / ContentProvider)。
dagger2.10中的@ Component.Builder 为我们提供了更好的方法来创建DaggerAppComponent的构建器。
Builder中的 @BindsInstance 会自动创建MyApplication
的实例,因此在AppModule
中我们不需要使用MyApplication进行实例化。它已经是图表中的依赖项。
ActivityBindingModule.clas 是我们的。我稍后会告诉你。
您可以在此处详细了解此部分:https://proandroiddev.com/dagger-2-component-builder-1f2b91237856
接下来是AppModule.class:
@Module
abstract class AppModule{
@Binds
abstract fun provideContext(application: MyApplication) : Context
@Module
companion object {
@JvmStatic
@Provides
fun provideSharedPreferences(context: Context): SharedPreferences =
context.getSharedPreferences("SharedPreferences", Context.MODE_PRIVATE)
}
}
@Binds 注释替换@Provides
注释,它只返回function参数中的值。如您所见,MyApplication的实例已经在图中,并且无需在AppModule构造函数中注入MyApplication。
注意:带@Binds注释的函数应该是抽象的,如果有带@Provides注释的函数,它们应该是static
。
Kotlin中的静态函数解决方案可以在这里找到:https://github.com/google/dagger/issues/900
ActivityBindingModule.class:
@Module
abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = [MainActivityModule::class])
internal abstract fun bindMainActivity(): MainActivity
}
使用 ActivityBindingModule 类,我们只需创建单独的模块,为我们的Android组件创建子组件。
有关ContributesAndroidInjector和Binds的更多信息,请参阅此处: https://proandroiddev.com/dagger-2-annotations-binds-contributesandroidinjector-a09e6a57758f
<强> MainActivityModule.class:强>
@Module
abstract class MainActivityModule {
@Binds
internal abstract fun provideMainActivity(activity: MainActivity): MainActivity
}
<强> MyApplication.class:强>
class MyApplication: DaggerApplication(){
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
val appComponent = DaggerAppComponent.builder()
.application(this)
.build()
appComponent.inject(this)
return appComponent
}
}
不要忘记在Mainfest文件中插入应用程序。
<application
android:name=".MyApplication"
...
>
...
</application>
对于您的Application类,您需要实现实现HasActivityInjector / HasFragmentInjector / etc的DaggerApplication以及调用AndroidInjection.inject()。
关于这一点,您可以在此处阅读更多内容:https://google.github.io/dagger/android.html
<强> MainActivity.class:强>
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var sharedPreferences: SharedPreferences
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("TAAAAG", sharedPreferences.toString())
}
}
正如您所看到的,MainActivity
现在不知道如何注入SharedPreferences。实际上DaggerAppCompatActivity中有AndroidInjection.inject(this);
。如果你不从此扩展你的课程,那么你需要自己在onCreate方法中指定它,否则不会进行注射。
修改强> 您可以查看GitHub中的代码:https://github.com/Belka1000867/Dagger2Kotlin