gh-pages / com.nextfaze.devfun.inject.dagger2 / InjectFromDagger2 / <init>

<init>

InjectFromDagger2()

This module adds rudimentary support for searching Dagger 2.x component graphs for object instances.

Due to limitations in KAPT it is not possible to generate Kotlin code that would then generate dagger bindings.Once this has been resolved it should be possible to resolve this more gracefully.

Automatic Reflection Based

On DevFunModule.initialize, your application (and its subclasses) are searched for a Component. This is assumed to be your top-level (singleton scoped) dagger component. An instance provider is then added referencing this instance.

At runtime (upon InstanceProvider.get) the component is traversed in a top-down fashion for a Provider or Module that Provides the requested type (or subclasses the type).

This has not been tested extensively beyond simple object graphs!

Annotation Based

Use Dagger2Component on functions/properties/getters that return components.

Provides some level of support for manually specifying scopes (any/or attempts to guess them based on the context).

Complex Object Graphs

A simple object graph is one that is linear; Singleton -> Activity -> Fragment -> etc., or one that only ever has a single type of some scope active at once. i.e. for the example below MyChildScope1 and MyChildScope2 - if only one of the ChildScope is active at a time. It should also work for branched scopes as long as the requested type iseffectively unique across scopes.

An example where this may fail:

Dagger 2 Scopes

If your dependency graph is too complicated you will need to provide your own instance provider with customized behaviour.

I am looking into better ways to support this - suggestions/PRs welcomed.

Custom Provider

A helper function tryGetInstanceFromComponent can be used to reduce the search scope.

See DemoInstanceProvider for this in use.

private class DemoInstanceProvider(private val application: Application, private val activityProvider: ActivityProvider) : InstanceProvider {
    private val applicationComponent by lazy { application.applicationComponent!! }

    override fun <T : Any> get(clazz: KClass<out T>): T? {
        tryGetInstanceFromComponent(applicationComponent, clazz)?.let { return it }

        activityProvider()?.let { activity ->
            if (activity is DaggerActivity) {
                tryGetInstanceFromComponent(activity.retainedComponent, clazz)?.let { return it }
                tryGetInstanceFromComponent(activity.activityComponent, clazz)?.let { return it }
            }
        }

        return null
    }
}

When supplying your own instance provider (but want to use tryGetInstanceFromComponent), set useAutomaticDagger2Injector to false to disable the default instance provider.

Add/remove providers using DevFun.instanceProviders.

See Also

Dagger2Component