匕首2不注入sharedPreference [英] Dagger 2 not injecting sharedPreference
问题描述
我是匕首2的新手,并尝试在下面的MyActivity类中注入sharedPreference的实例:
Hi i am new to dagger 2 and trying to inject an instance of sharedPreference inside my MyActivity class below:
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.
推荐答案
您做的有点不正确.首先,现在有了一个Dagger-android,它可以解决一些原理问题,该问题解决了组件(例如Activity)不应该知道注入如何发生的问题.
You have done it a little bit incorrect. First of all now there is dagger-android that helps with the problem of principle that solves the problem that components (such as Activities) should not know about how the injection happens.
您可以在此处阅读: https ://medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe
只需确保dagger依赖项位于Android项目中即可
Just to be sure that dagger dependencies are in the Android project:
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中设置与Subcomponent的连接,并且仅在MainAcitivy onCreate()方法中注入您的依存关系图.但是使用Dagger-android,一切都变得更加容易.
Your mistake is that you didn't tell to your graph that you want to make injections into the MainActivity. In the best way you should create Subcomponent
for MainActivity, connect it with another Module for MainActivity that have injections that you want to inject into the MainActivity, set in your AppComponent the connection with Subcomponent and only than in MainAcitivy onCreate() method inject your dependency graph. But with dagger-android everything is easier.
这是代码:
@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组件(活动/片段/服务/BroadcastReceiver/ContentProvider).
AndroidSupportInjectionModule.class : This goes from the dagger.android.support library. And it provides Android components (Activities/Fragments/Services/BroadcastReceiver/ContentProvider) with our module.
@ Component.Builder 为我们提供了更好的创建DaggerAppComponent构建器的方法.
@Component.Builder in dagger2.10 provides us better way to create a builder of DaggerAppComponent.
@BindsInstance 将自动创建MyApplication
的实例,因此在AppModule
中,我们不需要使用MyApplication实例化.它已经是图中的依赖项了.
@BindsInstance in the Builder will automatically create an instance of MyApplication
so in AppModule
we don't need to instantiate with MyApplication. It is already a dependency in the graph.
ActivityBindingModule.clas 是我们的.我待会再讲.
ActivityBindingModule.clas is our. I will tell about it later.
您可以在此处了解有关此部分的更多信息: https://proandroiddev.com/dagger -2-component-builder-1f2b91237856
You can read more about this part here: https://proandroiddev.com/dagger-2-component-builder-1f2b91237856
接下来是AppModule.class:
Next is 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
注释,它只是返回函数参数中的值.如您所见,图中已经存在MyApplication的实例,因此无需在AppModule构造函数中注入MyApplication.
@Binds annotation replaces @Provides
annotation and it just returns the value in the function parameter. As you see an instance of MyApplication is already in the graph and there is no need to inject MyApplication in the AppModule constructor.
注意:带有@Binds批注的函数应该是抽象的,如果存在带有@Provides批注的函数,它们应该是static
.
您可以在Kotlin中找到有关静态函数的解决方案: https://github.com/google/dagger /issues/900
NOTE: function with @Binds annotation should be abstract, and if there are function with @Provides annotation they should be static
.
The solution in Kotlin for static funcitons you can find here: https://github.com/google/dagger/issues/900
ActivityBindingModule.class:
@Module
abstract class ActivityBindingModule {
@ContributesAndroidInjector(modules = [MainActivityModule::class])
internal abstract fun bindMainActivity(): MainActivity
}
使用 ActivityBindingModule 类,我们仅创建了一个单独的模块,该模块将为我们的Android组件创建 Subcomponents .
With the ActivityBindingModule class we just create separate Module that will create Subcomponents for Android components for us.
有关ContributesAndroidInjector和Binds的更多信息,您可以在这里阅读: https://proandroiddev.com/dagger-2-annotations-binds-contributesandroidinjector-a09e6a57758f
More about ContributesAndroidInjector and Binds you can read here: 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.
Do not forget insert Application in the Mainfest file.
<application
android:name=".MyApplication"
...
>
...
</application>
对于您的Application类,您需要实现实现HasActivityInjector/HasFragmentInjector/etc的DaggerApplication并调用AndroidInjection.inject().
For your Application class you need to implement DaggerApplication that implements HasActivityInjector/HasFragmentInjector/etc as well as call AndroidInjection.inject().
关于此内容,您可以在此处了解更多信息: https://google.github.io/dagger/android.html
About this you can read more here : 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方法中指定它,否则将不会进行注入.
As you can see MainActivity
now does not know how SharedPreferences are injected. Actually there is AndroidInjection.inject(this);
in the DaggerAppCompatActivity. If you don't extend you class from this, than you need to specify it in onCreate method by yourself, otherwise no injections will be done.
您可以从GitHub检查代码: https://github.com/Belka1000867/Dagger2Kotlin
You can check the code from GitHub: https://github.com/Belka1000867/Dagger2Kotlin
这篇关于匕首2不注入sharedPreference的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!