匕首2不注入sharedPreference [英] Dagger 2 not injecting sharedPreference

查看:98
本文介绍了匕首2不注入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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆