Search code examples
androiddagger-2dagger

How to provide a dependency with @SessionScope and @ActivityScope using Dagger 2.10 Android Injector?


Suppose you have an application where user logs in on the first screen and, from that moment on, you have access to an User object. I would like to provide this dependency under a @SessionScope - it means, when user logs out, all dependencies provided through a component annotated as @SessionScope would die.

Despite the dependencies provides via @SessionScope I would like to have dependencies provided via @ActivityScope, an ActivityPresenter for instance and, of course, I would have to provide dependencies from @SessionScope and @ActivityScope together to an Activity consumer class.

What is the best to do it using Dagger 2 new AndroidInjector feature?

So far I'm able to provide dependencies under @ActivityScope like shown below:

@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class ActivityScope

@Module
abstract class ActivitiesBuilder {

    @ActivityScope
    @ContributesAndroidInjector(modules = arrayOf(HomepageModule::class, FacebookModule::class))
    abstract fun providesHomepageViewImpl(): HomepageViewImpl

}

@Module
abstract class AppModule {

    @Provides
    @Singleton
    fun provides (application: Application) : Context = application

}

@Singleton
@Component(
        modules = arrayOf(
                AndroidInjectionModule::class,
                ActivitiesBuilder::class,
                AppModule::class
        )
)
interface AppComponent : AndroidInjector<App> {

    @Component.Builder
    abstract class Builder : AndroidInjector.Builder<App>()

}

class App : DaggerApplication() {

    override fun onCreate() {
        super.onCreate()
        Timber.plant(Timber.DebugTree())
    }

    override fun applicationInjector(): AndroidInjector<out DaggerApplication> = DaggerAppComponent.builder().create(this)
}

Solution

  • Tutorial

    1. Create a custom scope named @SessionScope;
    2. Create a class named as SessionActivityBinding:
      • add a method that will bind the activity sub component that will be provided under session scope - further details on this implementation can be found here;
    3. Create a subcomponent named SessionComponent:
      • annotate this subcomponent with the custom scope created on step 1;
      • create a @Subcomponent.Builder and add a method that will receive a User object as parameter;
        • annotate this method with @BindsInstance;
        • add this method fun build(): SessionComponent in order to allow the provision of this SessionComponent - this will be necessary in order to release this component when user loggs out;
      • add SessionActivityBinding class into the module array;
      • [OPTIONAL]: Add a SessionModule class to provide dependencies that should be provided under @SessionScope;
    4. On AppModule add SessionComponent as a subcomponent;
    5. Add the AppModule in the list of module's from AppComponent;
    6. When user successfully authenticate into the system, and an User object is acquired, create an instance of SessionComponent that must remain live until user logs out;
    7. Whenever user logs out, discard the old instance of SessionComponent like: sessionComponent = null - this will discard all dependencies provided under @SessionScope;
    8. Whenever user logs in again, repeat the process from step 6;

    Further details and examples can be found here;