Why @ContributesAndroidInjector doesn't provide Android Framework type

左心房为你撑大大i 提交于 2019-12-02 15:59:22

问题


I have simplified my application to get the root of the problem and here is the simplified version. I'm implementing Dagger 2 using following configuration:

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}")
    }
}

When I run the application I get the following error. What I don't understand is ContributesAndroidInjector is already providing an instace of MainActivity why Dagger still complains about it.

MainActivity cannot be provided without an @Inject constructor or an @Provides-annotated method

EDIT for @yavor

Keep all classes as is and separate ActivityBindingModule implementation into two classes. Now you can see that instance of the MainActivity is provided and Dagger is not complaining about it. 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"
        }
    }
}

回答1:


What I don't understand is ContributesAndroidInjector is already providing an instace of MainActivity why Dagger still complains about it.

ContributesAndroidInjector in docs says:

Generates an {@link AndroidInjector} for the return type of this method. The injector is implemented with a {@link dagger.Subcomponent} and will be a child of the {@link dagger.Module}'s component.

So it does not provide MainActivity.

Why do you need it actually at all? I see that you are passing it as parameter to the function:

fun provideString(mainActivity: MainActivity)

but do you really need it there? In general you should inject dependencies in MainActivity. MainActivity should use them. If both(MainActivity and the string) they know about each other it is first - not a good design, and second: you are close to create cyclic dependencies which Dagger 2 does not support and throws exception.




回答2:


You probably forgot to inject your application in MyApp. You should have something like this (you might need to modify it a bit to fit your AppComponent:

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

Also, Dagger is actually providing your MainActivity through your @ContributesAndroidInjector annotated method but that's not what you're injecting.

You're injecting a string so Dagger is using your provideString method. Since this method requires a MainActivity instance to work, Dagger is looking for such a method annotated with @Provides. You don't have any and Dagger won't look at your @ContributesAndroidInjector method since it does not have any reasons to do so.

If you want it to work, you actually have to define your provideString method in a separate module and install it inside your @ContributesAndroidInjector:

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

@Module
class StringModule {

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


来源:https://stackoverflow.com/questions/58712860/why-contributesandroidinjector-doesnt-provide-android-framework-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!