Изучаю AndroidInjector, практикуясь на простом приложении с иерархией App -> MainActivity -> MainFragment.
У каждого из них есть модуль, который предоставляет простую строку. Например:
@Module
class AppModule {
@Named("app string")
@Provides
fun provideAppString(): String {
return "Dagger app string"
}
}
Приложение работает, но только вот с таким компонентом:
@Singleton
@Component(modules = [AndroidInjectionModule::class, ActivityProvider::class,FragmentProvider::class, AppModule::class, ActivityModule::class, FragmentModule::class])
interface AppComponent : AndroidInjector<DaggerApplication>
Провайдеры активити и фрагмента похожие :
@Module
abstract class ActivityProvider {
@ContributesAndroidInjector
abstract fun mainActivity(): MainActivity
}
Я хочу убрать ActivityModule и FragmentModule в соответствующие провайдеры вот так:
@Module
abstract class FragmentProvider {
@ContributesAndroidInjector(modules = [FragmentModule::class])
abstract fun mainFragment(): MainFragment
}
Для фрагмента это работает, но если сделать тоже самое для activity - приложение не билдится. Что то не так с инжектом в активити:
/home/x/GIT/DI/app/build/tmp/kapt3/stubs/debug/com/app/di/di/AppComponent.java:8: error: [Dagger/MissingBinding]
javax.inject.Named("activity string") java.lang.String cannot be provided without an @Provides-annotated method.
public abstract interface AppComponent extends dagger.android.AndroidInjector {
^
javax.inject.Named("activity string") java.lang.String is injected at
com.app.di.ui.fragment.MainFragment.activityString
com.app.di.ui.fragment.MainFragment is injected at
dagger.android.AndroidInjector.inject(T) [com.app.di.di.AppComponent → com.app.di.di.FragmentProvider_MainFragment.MainFragmentSubcomponent]
Полный код Activity и ее компонентов:
@Singleton
@Component(modules = [AndroidInjectionModule::class, ActivityProvider::class,FragmentProvider::class, AppModule::class])
interface AppComponent : AndroidInjector<DaggerApplication>
@Module
abstract class ActivityProvider {
@ContributesAndroidInjector(modules = [ActivityModule::class])
abstract fun mainActivity(): MainActivity
}
@Module
class ActivityModule {
@Named("activity string")
@Provides
fun provideActivityString(): String {
return "Dagger activity string"
}
}
class MainActivity : DaggerAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container_view, MainFragment::class.java, null)
.commit()
}
}
companion object {
private const val TAG = "MainActivity"
}
}
class MainFragment : DaggerFragment(R.layout.fragment_main) {
@Inject
@Named("app string")
lateinit var appString: String
@Inject
@Named("activity string")
lateinit var activityString: String
@Inject
@Named("fragment string")
lateinit var fragmentString:String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.i(TAG, "onCreate: $appString, $activityString, $fragmentString")
}
companion object {
private const val TAG = "MainFragment"
}
}