Classy Data

Dagger 2 Dependency Injection
Classy Data object dependencies are resolved at runtime using Dagger 2 - A fast dependency injector for Android and Java. The benefits of using dependency injection are having loosely coupled classes that can be wired together easily in various ways to adapt for different platforms, available resources and operational requirements. The benefits of using Dagger dependency injection is rapid development and performance through harnessing the power of the Java compiler.

Annotations

Dagger supports both constructor and field injection. Constructor injection is specified in @Module-annotated classes provided by the programmer, with @Provides annotated methods supplying the dependency objects. Dagger generates injection code at compile time, providing timely information of dependency configuration errors. An @Module-annotated class example is shown on the right.

Fields to be injected are annotated in-situ with @Inject and field injection is used where it is not possible to use constructor injection eg. for subclasses of Android Activity.class.

Components, Subcomponents and Scopes

@Component and @Subcomponent annotations are applied to interfaces which specify object factories Dagger is required to generate at compile time. A Component factory represents an object graph of class dependencies which endure for the life of the application. A Subcomponent factory keeps objects only while the scope in which they are created exists. A scope can be identified using a custom annotation to make it more tangible eg. @UserScope associated with a user login session. A Subcomponent is a child of a Component and conveniently inherits the parent's object graph. One use of a Subcomponent is to create an object to perform a persistence task running in a separate thread. Once the task completes and calls back to the calling thread, the persistence task object is discarded. When the @Singleton annotation is applied to a Component factory method, then a single object instance is created which lasts for the duration of the application - ie. the object has application scope. Note that every object specified in the @Module class opposite has application scope.

Application-scope Module example from Many to Many Example

import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
...
@Module
public class ManyToManyModule
{
...
public ManyToManyModule(ResourceEnvironment resourceEnvironment)
{
this.resourceEnvironment = resourceEnvironment;
}

@Provides @Singleton ThreadHelper provideSystemEnvironment()
{
return new TestSystemEnvironment();
}

@Provides @Singleton TaskManager provideTaskManager()
{
return new TaskManager();
}

@Provides @Singleton ResourceEnvironment provideResourceEnvironment()
{
return resourceEnvironment;
}

@Provides @Singleton DatabaseSupport provideDatabaseSupport()
{
sqliteDatabaseSupport = new SQLiteDatabaseSupport(ConnectionType.memory);
return sqliteDatabaseSupport;
}

@Provides @Singleton PersistenceFactory providePersistenceFactory(DatabaseSupport databaseSupport, ResourceEnvironment resourceEnvironment)
{
return new PersistenceFactory(databaseSupport, resourceEnvironment);
}

@Provides @Singleton ConnectionSourceFactory provideConnectionSourceFactory()
{
return sqliteDatabaseSupport;
}

@Provides @Singleton PersistenceContext providePersistenceContext(PersistenceFactory persistenceFactory, ConnectionSourceFactory connectionSourceFactory)
{
return new PersistenceContext(persistenceFactory, connectionSourceFactory);
}
}