Refer to Setup Dagger 2 For Android Kotlin for general Dagger 2 setup with Activity, while this article shall focus on dependency injection in Fragment
only.
NOTE: This article depends on classes declared in Setup Dagger 2 For Android Kotlin.
Application Class
Add HasSupportFragmentInjector
and fragmentInjector
to Application
class.
class LuaApp : Application(), HasActivityInjector, HasSupportFragmentInjector { @Inject lateinit var activityInjector: DispatchingAndroidInjector<Activity> @Inject lateinit var fragmentInjector: DispatchingAndroidInjector<Fragment> override fun onCreate() { super.onCreate() // initialize Dagger DaggerAppComponent.builder().application(this).build().inject(this) } override fun activityInjector(): AndroidInjector<Activity> = activityInjector override fun supportFragmentInjector(): AndroidInjector<Fragment> = fragmentInjector}
NOTE: If the above is not configured properly, you will bump into exception Caused by: java.lang.IllegalArgumentException: No injector was found for ...
when AndroidSupportInjection.inject
is called in Fragment
.
FragmentModule
Create FragmentModule
class to declare Fragment
for injection.
@Moduleabstract class FragmentModule { @ContributesAndroidInjector internal abstract fun contributePhotoPinListFragment(): PhotoPinListFragment}
AppComponent
Edit AppComponent
to include @Component(modules = [..., (FragmentModule::class)])
@Singleton@Component(modules = [(AndroidInjectionModule::class), (AppModule::class), (ActivityModule::class), (FragmentModule::class)])interface AppComponent { @Component.Builder interface Builder { @BindsInstance fun application(application: Application): Builder fun build(): AppComponent } fun inject(luaApp: LuaApp)}
Fragment
Include AndroidSupportInjection.inject
at Fragment.onAttach
.
Access ViewModel
at Fragment.onActivityCreated
.
class PhotoPinListFragment : Fragment() { @Inject lateinit var viewModelFactory: ViewModelFactory private lateinit var viewModel: PhotoPinListViewModel override fun onActivityCreated(savedInstanceState: Bundle?) { viewModel = ViewModelProviders.of(this, viewModelFactory).get(PhotoPinListViewModel::class.java) } override fun onAttach(context: Context) { AndroidSupportInjection.inject(this) super.onAttach(context) }}
ViewModelModule
Remember to declare PhotoPinListViewMode
at ViewModelModule
.
@Moduleinternal abstract class ViewModelModule { @Binds @IntoMap @ViewModelKey(MainViewModel::class) abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel @Binds @IntoMap @ViewModelKey(PhotoPinListViewModel::class) abstract fun bindPhotoPinListViewModel(viewModel: PhotoPinListViewModel): ViewModel}
References: