Tsudzukeru
@Tsudzukeru

Как выстроить организацию модулей Dagger(AndroidInjector)?

Изучаю 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"
    }
}
  • Вопрос задан
  • 167 просмотров
Решения вопроса 1
zagayevskiy
@zagayevskiy Куратор тега Android
Android developer at Yandex
Я не увидел, где у тебя объявлено, что сгенерированный компонент фрагмента будет сабкомпонентом для компонента активити. Если это не так(а это не так), то эта твоя стринга находится в другой части графа, и, конечно, получить к ней доступ не получится.
Я думаю, что в ActivityProvider в ContributesAndroidInjector(modules) ты должен также указывать FragmentProvider. Тогда код нагенерится правильно.

А, соответственно, в AppComponent должны остаться только AndroidInjectionModule, AppModule, и ActivityProvider.

Вот это можно почитать https://m.habr.com/ru/post/336462/
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы