Eixx
Eixx

Reputation: 313

Dagger 2 subcomponent across Android modules

Recently I started to divide our application into smaller Android modules, but I can't figure out how to structure dagger so it works for me.

My approach is to divide "bigger" features into smaller modules. Most of my features is within a base module for now.

What I have working right now:

         App
          ^ 
          |
         Base
          ^
          |
      Mvvm core

MyDagger setup consists of:
- a @Singleton scoped AppComponent
- a @UserScope subcomponent UserComponent

Both of which is placed in the Base module.

What I'm trying to achieve:

         App
          ^ 
          |
Feature 1 - Feature 2
          ^
          |
         Base
          ^
          |
      Mvvm core

My plan is that each feature will have a @FeatureX subcomponent within their own module - but this is where everything falls apart.

I can't figure out how to expose the SubComponent.Build to each of my feature modules.

Is this even the right approach or what am I missing?

Bonus info: I have also tried to move the AppComponent & UserComponent into the App module, but then I lack access to the component, which I need for injection, from my feature module(s).

Upvotes: 0

Views: 277

Answers (1)

Benjamin
Benjamin

Reputation: 7368

Let's say you've created an android module named cookie which contains an activity and a dagger module.

CookieActivity:

class CookieActivity : DaggerAppCompatActivity() {

    @Inject
    lateinit var name: String

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_cookie)

        findViewById<TextView>(R.id.name).text = name
    }
}

CookieModule:

@Module
abstract class CookieModule {

    @ContributesAndroidInjector
    abstract fun cookieActivity(): CookieActivity

    @Module
    companion object {

        @Provides
        @JvmStatic
        fun provideName() = "Oreo"
    }
}

Now you want to use this CookieActivity from your main application. First you need to create your AppComponent (note that the CookieModule is installed inside the component):

@Singleton
@Component(modules = [AndroidSupportInjectionModule::class, CookieModule::class])
interface AppComponent : AndroidInjector<App>

Then make your Application class able to inject activity and fragment:

class App : Application(), HasActivityInjector, HasSupportFragmentInjector {

    @Inject
    internal lateinit var dispatchingActivityInjector: DispatchingAndroidInjector<Activity>

    @Inject
    internal lateinit var dispatchingFragmentInjector: DispatchingAndroidInjector<Fragment>

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.builder()
            .build()
            .inject(this)
    }
    override fun activityInjector(): AndroidInjector<Activity>? {
        return dispatchingActivityInjector
    }

    override fun supportFragmentInjector(): AndroidInjector<Fragment>? {
        return dispatchingFragmentInjector
    }
}

You can now use your CookieActivity and the main application will take care of the injection:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        findViewById<Button>(R.id.button).setOnClickListener {
            val intent = Intent(this, CookieActivity::class.java)
            startActivity(intent)
        }
    }
}

"Oreo" will be shown as provided by the CookieModule.

Upvotes: 1

Related Questions