Почему @ContributesAndroidInjector не предоставляет тип Android Framework - PullRequest
0 голосов
/ 05 ноября 2019

Я упростил свое приложение, чтобы получить корень проблемы, и вот упрощенная версия. Я реализую Dagger 2, используя следующую конфигурацию:

AppComponent

@Component(modules = [
    AndroidSupportInjectionModule::class,
    ActivityBindingModule::class
])
interface AppComponent: AndroidInjector<MyApp> {
    @Component.Builder
    interface Builder{
        @BindsInstance
        fun application(application: Application): Builder

        fun build(): AppComponent
    }
}

ActivityBindingModule

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector
    abstract fun mainActivity(): MainActivity

    @Module
    companion object{
        @JvmStatic
        @Provides
        fun provideString(mainActivity: MainActivity): String{
            return "Tent"
        }
    }
}

MainActivity

class MainActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var string: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        println("meco simplest ${string}")
    }
}

Когда я запускаю приложение, я получаю следующую ошибку. Я не понимаю, что ContributesAndroidInjector уже предоставляет MainActivity причину, по которой Даггер все еще жалуется на это.

MainActivity не может быть предоставлена ​​без конструктора @Inject или аннотации @ Provides-annotatedМетод

РЕДАКТИРОВАТЬ для @ yavor

Сохранить все классы как есть и разделить реализацию ActivityBindingModule на два класса. Теперь вы можете видеть, что экземпляр MainActivity предоставлен, и Кинжал не жалуется на это. ActivityBindingModule

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector(modulese [StringProviderModule::class])
    abstract fun mainActivity(): MainActivity
}

StringProviderModule

@Module
class StringProviderModule {
    @Module
    companion object{
        @JvmStatic
        @Provides
        fun provideString(mainActivity: MainActivity): String{
            return "Tent"
        }
    }
}

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Чего я не понимаю, так это того, что ContributesAndroidInjector уже предоставляет объект MainActivity, почему Даггер все еще жалуется на это.

ContributesAndroidInjector в документах говорит:

Создает {@link AndroidInjector} для возвращаемого типа этого метода. Инжектор реализован с помощью {@link dagger.Subcomponent} и будет дочерним по отношению к компоненту {@link dagger.Module}.

Поэтому он не обеспечивает MainActivity.

Зачем вам это вообще нужно? Я вижу, что вы передаете его в качестве параметра в функцию:

fun provideString (mainActivity: MainActivity)

но вам это действительно нужно там? В общем случае вы должны вводить зависимости в MainActivity. MainActivity должен их использовать. Если оба (MainActivity и строка) знают друг о друге, то во-первых - не очень хороший дизайн, а во-вторых: вы близки к созданию циклических зависимостей, которые Dagger 2 не поддерживает и выдает исключение.

1 голос
/ 05 ноября 2019

Вы, вероятно, забыли ввести заявку в MyApp. У вас должно быть что-то вроде этого (вам может понадобиться немного изменить его, чтобы он соответствовал вашему AppComponent:

DaggerAppComponent.builder()
    .application(this)
    .build()
    .inject(this)

Кроме того, Dagger фактически предоставляет ваш MainActivity с помощью аннотированного метода @ContributesAndroidInjector, но этоне то, что вы вводите.

Вы вводите string, поэтому Dagger использует ваш метод provideString. Поскольку для этого метода требуется экземпляр MainActivity, Dagger ищет такой методс пометкой @Provides. У вас ее нет, и Dagger не будет смотреть на ваш метод @ContributesAndroidInjector, поскольку у него нет никаких причин для этого.

Если вы хотите, чтобы он работал, вы на самом деленеобходимо определить ваш метод provideString в отдельном модуле и установить его внутри вашего @ContributesAndroidInjector:

@Module
abstract class ActivityBindingModule {
    @ContributesAndroidInjector(modules = [StringModule::class])
    abstract fun mainActivity(): MainActivity
}

@Module
class StringModule {

    @JvmStatic
    @Provides
    fun provideString(mainActivity: MainActivity): String = "Hehe"
}
...