Guowei Lv

1 minute read

Let’s create a ScreensNavigator interface:

interface ScreensNavigator {
    fun navigateBack()
    fun toQuestionDetails(questionId: String)
}

And ScreensNavigatorImpl implements it:

class ScreensNavigatorImpl @Inject constructor(private val activity: AppCompatActivity) :
    ScreensNavigator {

    override fun navigateBack() {
        activity.onBackPressed()
    }

    override fun toQuestionDetails(questionId: String) {
        QuestionDetailsActivity.start(activity, questionId)
    }
}

Now we have a problem that in activities and fragments we want to inject the interface type:

@Inject
lateinit var screensNavigator: ScreensNavigator

But Dagger only knows how to create ScreensNavigatorImpl. How can we help Dagger to figure out when we want an ScreensNavigator, we need an instance of ScreensNavigatorImpl? The trick is to use @Binds.

@Module
abstract class ActivityModule {

    @ActivityScope
    @Binds
    abstract fun screensNavigator(screensNavigatorImpl: ScreensNavigatorImpl): ScreensNavigator

    /**
     * Moved these to companion object because otherwise we get this error
     * A @Module may not contain both non-static and abstract binding method
     */
    companion object {
        @Provides
        fun layoutInflater(activity: AppCompatActivity): LayoutInflater =
            LayoutInflater.from(activity)

        @Provides
        fun fragmentManager(activity: AppCompatActivity) = activity.supportFragmentManager
    }
}

Now that we have to make ActivityModule an abstract class, we need to remove fun activityModule() from ActivityComponent.Builder. And Dagger knows how to construct abstract Modules by itself.

comments powered by Disqus