google/dagger

[ASK] AndroidInjector Builder to Factory Migration

wahyupermadie opened this issue · 6 comments

Hi team, currently I want to migrate from AndroidInjector.Builder to AndroidInjector.Factory, currently my implementation is like this one, and here I use Dagger Android. I'm stuck on how we migrate it, since in Factory we don't have seedInstance, and using SubComponent.Factory / Component.Factory only accepts an abstract method that is already provided by AndroidInjector.Factory. Is there any alternative to archive this ?

Current Implementation

abstract class BaseAndroidInjectorBuilder<T> : AndroidInjector.Builder<T> {

    override fun seedInstance(instance: T): AndroidInjector<T> {
        superInstance(instance)
        superInstance2(instance)
    }

    @BindsInstance
    abstract fun superInstance(instance: Activity)
    
    @BindsInstance
    abstract fun superInstance2(instance: ActivitySnackbar)
}

And I usually use like this one

@Subcomponent
interface SubActivitySubcomponent : AndroidInjector<SubActivity> {

    @Subcomponent.Builder
    abstract class Builder : BaseAndroidInjectorBuilder<SubActivity>()

}

Module

    @Binds
    @IntoMap
    @ClassKey(SubActivity::class)
    abstract fun provideSubActivitySubcomponent(builder: SubActivitySubcomponent.Builder): AndroidInjector.Factory<*>

I don't think the seedInstance is necessary, since if you use AndroidInjector.Factory, it binds the activity to the Dagger graph, so you should be able create a separate module to provide superInstance and superInstance2 with @Binds.

@Binds
abstract fun superInstance2(instance: SubActivity): ActivitySnackbar

Hi @wanyingd1996 but how if I provide some impl like this ?

abstract class BaseAndroidInjectorBuilder<T> : AndroidInjector.Builder<T> {

    override fun seedInstance(instance: T): AndroidInjector<T> {
        superInstance(instance)
        superInstance2(ActivitySnackbarImpl.create(instance))
    }

    @BindsInstance
    abstract fun superInstance(instance: Activity)
    
    @BindsInstance
    abstract fun superInstance2(instance: ActivitySnackbar)
}

I mean you don't need BaseAndroidInjectorBuilder anymore. Just use the factory

@Subcomponent
interface SubActivitySubcomponent : AndroidInjector<SubActivity> {
    @Subcomponent.Factory
    interface Factory : AndroidInjector.Factory<SubActivity>()
}

and a module

@Module
object someModule {
  @Binds
  abstract fun superInstance(instance: SubActivity): Activity

  @Binds
  abstract fun superInstance2(instance: SubActivity): ActivitySnackbar
}

This does the same thing as your current implementation

Hi @wanyingd1996 thanks for you replied, but seems that not the same, since ActivitySnackbar i need to provide this by calling ActivitySnackbarImpl.create(instance) so cannot using the SubActivity reference directly. I think if I want to do that, the only way I can think of is by doing like this

@Subcomponent
interface SubActivitySubcomponent : AndroidInjector<SubActivity> {
    @Subcomponent.Factory
    interface Factory {
        fun create(@BindsInstance activity: SubActivity, @BindsInstance activitySnackbar: ActivitySnackbar): SubActivitySubcomponent
    }
}

but yah, i cannot use the AndroidInjector.Factory,

The example you shared in your initial code snippet is passing SubActivity instance to superInstance2, and directly use @BindsInstance, which means your are providing the SubActivity instance as ActivitySnackbar.

Are you saying what you actually want is:

    override fun seedInstance(instance: T): AndroidInjector<T> {
        superInstance(instance)
        superInstance2(ActivitySnackbarImpl.create(instance))
    }

If this is the case, you can just change my suggested module implementation to be:

@Module
object SomeModule {
  @Binds
  abstract fun superInstance(instance: SubActivity): Activity

  @Provides
  fun superInstance2(instance: SubActivity): ActivitySnackbar = ActivitySnackbarImpl.create(instance)
}

There is no need to use @BindsInstance for activitySnackbar if its only dependency is SubActivity, which is already bind to the dagger graph via the factory.

Yes, that's also things I want to proceed with, I moved out all the object inside seedInstance to a module and included them in the subcomponent module as well, I just want to make minimal changes to my current project since many instance was init during seedInstance, since moving to a module require extra works.

thanks for your help @wanyingd1996, really appreciate it. I will close this thread