Wednesday, 23 October 2019

Injecting fragment with activity reference

I have a class DashboardActivity with two fragments, A and B, in a viewpager. Each Fragment has its own ViewModel, AViewModel and BViewModel, respectively.

Now currently I'm creating a Subcomponent for the DashboardActivity, which binds both viewmodel instances and injects them into the fragments via ContributesAndroidFragment.

How could I create a Subcomponent per Fragment, so that dependencies requiring an activity (in this case NavigationController) could still be fullfilled? i.e. How can I create this subcomponent by providing the activity the fragment is being attached to?

Consider that these fragments could be added elsewhere in the app so the attaching activity could be different in runtime.

This is how I've done it:

AppComponent:

@Singleton
@Component(
        modules = [
            ApplicationModule::class,
            AndroidSupportInjectionModule::class,
            NetModule::class,
            ...
            ActivityBindings::class
        ]
)
interface ApplicationComponent : AndroidInjector<MyApp> {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: Application): ApplicationComponent
    }
}

ActivityBindings:

@Module
abstract class ActivityBindings {
    @ContributesAndroidInjector(modules = [DashboardModule::class])
    @PerActivity
    abstract fun dashboardModule(): DashboardActivity
    ...
}

DashboardModule:

@Module(includes = [CommonActivityModule::class])
abstract class DashboardModule {

    @Binds
    abstract fun bindsActivity(activity: DashboardActivity): AppCompatActivity

    @ContributesAndroidInjector
    abstract fun contributeFragmentA(): FragmentA

    @ContributesAndroidInjector
    abstract fun contributesFragmentB(): FragmentB


    @Binds
    @IntoMap
    @ViewModelKey(BViewModel::class)
    @PerActivity
    internal abstract fun bViewModel(bViewModel: BViewModel): ViewModel

    @Binds
    @IntoMap
    @ViewModelKey(AViewModel::class)
    @PerActivity
    internal abstract fun aViewModel(aViewModel: AViewModel): ViewModel

}

CommonActivityModule:

@Module(includes = [ViewContainerModule::class, ViewModelBuilder::class])
abstract class CommonActivityModule {

    @Binds
    @ForActivity
    abstract fun bindsContext(activity: AppCompatActivity): Context

    @Module
    companion object {

        @Provides
        @PerActivity
        @JvmStatic
        fun provideNavigationController(activity: AppCompatActivity) = NavigationController(activity)
    }
}

PS. I need to be able to inject more fragments from fragmentA and fragmentB, so they should also act as AndroidInjectors



from Injecting fragment with activity reference

No comments:

Post a Comment