Application context injection in library module with dagger 2

I am creating an application with some functionality: ContentProvider - SyncAdapter, Job service and associated persistence logic. In addition to these, there are Events with a user interface. I am trying to put all the mentioned functions in a separate library module because in theory their logic is self-contained and can be reused by any application.

Now comes Dagger2. The first node (main component) of my library dependency graph should provide a Context, and this Context should be injected from the Application since the library scope has the same application lifecycle. Obviously, my library shouldn't use my application class directly.

These are the possibilities I was thinking about:

  • Create a main library component in my application and store it in a global static class / enum as suggested here , but I'm concerned that using such a static reference might be anti-pattern.
  • Package in a library an application class that creates a library scoped component, attaches an application context to that class in the library to use that component, and then extends that application class into the main application. This works, but if there is more than one library in there, it won't be any more viable.
  • Use a factory pattern: put expose methods in a library component that expose a factory, which in turn receives a locally available context as a parameter. (As explained here ). This seems viable, although it adds additional complexity.
  • Last but not least, abandon the attempt to modulate components, as reliance on application context violates the concept of modularity.

What is the correct way to do this?

+2


source to share


1 answer


Dagger 2 for Android comes to the rescue. It provides a concept AndroidInjector

that is Component

that can be used to encapsulate an instance in a static way, without having to know the dependency provider. Moreover, using the Dagger-

prefix classes provided out of the box, nested dependencies appear to come from nowhere. Tall.

All you have to do is declare the top level in the library Module

, which is set in the application Component

. This one Module

will provide all the dependencies and the SubComponent

required library, which automatically inherit @AppContext Context

that you seeded in the dependency graph, ready to be injected anywhere in your library, as well as every dependency you through the main application Component

.

Here's a short example (written in Kotlin):

@Component(modules = [
    AndroidSupportInjectionModule::class,
    AppModule::class,
    LibraryModule::class //plug-in the library to the dependency graph
])
@Singleton
interface AppComponent : AndroidInjector<App> {

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

        @BindsInstance
        abstract fun appContext(@AppContext context: Context)

        override fun seedInstance(instance: App) {
            appContext(instance)
        }
    }
}

      

Edit: extended examples

An example of an Application subclass:



// DaggerApplication provides out-of-the-box support to all the AndroidInjectors.
// See the class' code to understand the magic.
public class App extends DaggerApplication {

@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
    // We only provide its own Injector, the Application Injector,
    // that is the previous AppComponent
    return DaggerAppComponent.builder().create(this);
}

      

And in your android library:

@Module
public abstract class LibraryModule {

    @ContributesAndroidInjector
    public abstract LibraryActivity contributeLibraryActivityInjector();

}

      


public class LibraryActivity extends DaggerAppCompatActivity {

    @Inject
    @AppContext
    Context appContext;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceSate);
        // here you automagically have your injected application context!
        ExternalSingleton.getInstance(appContext)
    }
}

      

+2


source







All Articles