Android Dagger 2 Injection For Fragment (Kotlin)

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:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.