Инъекционный фрагмент с указанием активности - PullRequest
4 голосов
/ 21 октября 2019

У меня есть класс DashboardActivity с двумя фрагментами, A и B, в окне просмотра. Каждый фрагмент имеет свои собственные ViewModel, AViewModel и BViewModel соответственно.

В настоящее время я создаю Subcomponent для DashboardActivity, который связывает оба экземпляра viewmodel и внедряет их вфрагменты через ContributesAndroidFragment.

Как я могу создать подкомпонент на фрагмент, чтобы зависимости, требующие действия (в данном случае NavigationController), все еще могли быть заполнены? т.е. как я могу создать этот подкомпонент, предоставив действие, к которому прикрепляется фрагмент?

Учтите, что эти фрагменты могут быть добавлены в другом месте приложения, чтобы действие присоединения могло отличаться во время выполнения.

Вот как я это сделал:

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. Мне нужно иметь возможность вставлять больше фрагментов из fragmentA и fragmentB, поэтому они также должны действовать как AndroidInjectors

...