Dagger 2没有注入sharedPreference

时间:2018-01-03 17:02:38

标签: android dependency-injection kotlin dagger-2

您好我是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.

1 个答案:

答案 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