嗨,我是匕首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.
aleksandrbel.. 7
您做的有点不正确。首先,现在有了Dagger-android,它可以解决一些原理性问题,该问题解决了组件(例如Activity)不应该知道注入如何发生的问题。
您可以在这里阅读:https : //medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe
只是为了确保匕首依赖项在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。以最佳方式应该Subcomponent
为MainActivity 创建,将其与另一个MainActivity模块连接,该模块具有要注入到MainActivity中的注入,在AppComponent中设置与Subcomponent的连接,并且仅在MainAcitivy onCreate()方法中注入依赖关系图。但是使用Dagger-android,一切都变得更加容易。
这是代码:
@Singleton @Component(modules = [ AndroidSupportInjectionModule::class, ActivityBindingModule::class, AppModule::class ]) interface AppComponent : AndroidInjector{ 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)。
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
注释,它只返回函数参数中的值。如您所见,图中已经存在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类,我们只创建了一个单独的Module,它将为我们为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{ val appCompOnent= DaggerAppComponent.builder() .application(this) .build() appComponent.inject(this) return appComponent } }
不要忘记在Mainfest文件中插入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。实际上AndroidInjection.inject(this);
在DaggerAppCompatActivity中。如果您不从中扩展您的类,那么您需要自己在onCreate方法中指定它,否则将不会进行注入。
编辑: 您可以从GitHub检查代码:https : //github.com/Belka1000867/Dagger2Kotlin
您做的有点不正确。首先,现在有了Dagger-android,它可以解决一些原理性问题,该问题解决了组件(例如Activity)不应该知道注入如何发生的问题。
您可以在这里阅读:https : //medium.com/@iammert/new-android-injector-with-dagger-2-part-1-8baa60152abe
只是为了确保匕首依赖项在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。以最佳方式应该Subcomponent
为MainActivity 创建,将其与另一个MainActivity模块连接,该模块具有要注入到MainActivity中的注入,在AppComponent中设置与Subcomponent的连接,并且仅在MainAcitivy onCreate()方法中注入依赖关系图。但是使用Dagger-android,一切都变得更加容易。
这是代码:
@Singleton @Component(modules = [ AndroidSupportInjectionModule::class, ActivityBindingModule::class, AppModule::class ]) interface AppComponent : AndroidInjector{ 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)。
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
注释,它只返回函数参数中的值。如您所见,图中已经存在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类,我们只创建了一个单独的Module,它将为我们为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{ val appCompOnent= DaggerAppComponent.builder() .application(this) .build() appComponent.inject(this) return appComponent } }
不要忘记在Mainfest文件中插入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。实际上AndroidInjection.inject(this);
在DaggerAppCompatActivity中。如果您不从中扩展您的类,那么您需要自己在onCreate方法中指定它,否则将不会进行注入。
编辑: 您可以从GitHub检查代码:https : //github.com/Belka1000867/Dagger2Kotlin