DaggerSharpener is an Android library which simplifies the creation of a Dagger2 dependency graph while helping mentain the code more readable. This library comes as an extension for Dagger2.
In this repository you can find an example project showing its usage as well as the library projects. The example is replicating the following dagger2 tutorial project (using Dagger2 + DaggerSharpener): https://github.com/patrick-doyle/dagger2-tutorial
// Add DaggerSharpener and Dagger2 dependencies
dependencies {
implementation 'com.github.alexdochioiu:daggersharpener:0.1.0'
annotationProcessor 'com.github.alexdochioiu:daggersharpener-processor:0.1.0'
implementation 'com.google.dagger:dagger:2.17'
annotationProcessor 'com.google.dagger:dagger-compiler:2.17'
}@ModulepublicclassMyModule {
@ProvidesObjectmyObject() {
returnnewObject();
}
}Note: As you can see, no scope has yet been given to the object. This will be addressed in the following steps.
@SharpComponent(
modules=MyModule.class // array of multiple modules can be provided as {A.class, B.class, ...}
)
publicclassMyApplicationextendsApplication {
}After building, two files are generated:
SharpMyApplicationComponent.java -- (Names is formed as: Sharp + Class Name + Component)
@Component@SharpMyApplicationScopepublicinterfaceSharpMyApplicationComponent {
MyApplicationinject(MyApplicationthisClass);
}SharpMyApplicationScope.java -- (Names is formed as: Sharp + Class Name + Scope)
@Scope@Retention(RetentionPolicy.RUNTIME)
public@interfaceSharpMyApplicationScope {}@ModulepublicclassMyModule {
@Provides@SharpMyApplicationScopeObjectmyObject() {
returnnewObject();
}
}@SharpComponent(
modules=MyModule.class
)
publicclassMyApplicationextendsApplication {
privateSharpMyApplicationComponent sharpComponent;
@InjectObject injectedObject;
@OverridepublicvoidonCreate() {
super.onCreate();
// Name is: Dagger + Sharp + Class Name + Component
sharpComponent =DaggerSharpMyApplicationComponent.builder().build();
sharpComponent.inject(this);
Log.d("MyApplication", "onCreate: "+ injectedObject.toString());
}
publicSharpMyApplicationComponentgetSharpComponent() {
return sharpComponent;
}
}Note: By running the code and checking logcat, you will see that the injectedObject is non-null. This indicates our object got successfully injected.
@SharpComponent(
dependencies=SharpMyApplicationComponent.class
)
publicclassMainActivityextendsAppCompatActivity {
@OverrideprotectedvoidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}Note: The new Sharp Activity Component depends on SharpMyApplicationComponent
After building, two new files are generated:
SharpMainActivityComponent.java
@Component@SharpMainActivityScopepublicinterfaceSharpMainActivityComponent {
MainActivityinject(MainActivitythisClass);
}SharpMainActivityScope.java
@Scope@Retention(RetentionPolicy.RUNTIME)
public@interfaceSharpMainActivityScope {}@SharpComponent(
modules=MyModule.class,
provides=Object.class // Array of dependencies can be provided as {A.class, B.class, etc.}
)
publicclassMyApplicationextendsApplication {
...
}@SharpComponent(
sharpDependencies=MyApplication.class // The class(es) annotated with @SharpComponent
)
publicclassMainActivityextendsAppCompatActivity {
@InjectObject myObject;
@OverrideprotectedvoidonCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerSharpMainActivityComponent.builder()
.sharpMyApplicationComponent(((MyApplication) getApplication()).getSharpComponent())
.build()
.inject(this);
Log.d("MainActivity", "onCreate: "+ myObject.toString());
}
}Note: By running the code and checking logcat, you will see that injectedObject from MyApplication and myObject from MainActivity are indeed the same instance (as long as you did the step 2.2). If you did not do step 2.2, the instance will be different for the two objects.
Using DaggerSharpener will still allow you to use @Inject on constructors. Also, the generated scopes can be safely used on the classes which inject constructors.
For some docs, keep on reading below!
Takes an array of dagger2 modules
Takes an array of classes annotated as@SharpComponent which will serve as dependencies for this new sharp component which is to be generated.
Takes an array of dagger2 components which will serve as dependencies for this new sharp component which is to be generated. This is to allow the developer to mix manually created dagger2 components and sharp components. Note: sharpDependencies and dependencies can be used together safely
If you want to use a manually created scope, you can give it there. If you do so, no scope will be generated for this sharp component.
The array of (un-named) classes to be provided to the dependants of this sharp component
The array of @NamedPair entries. Each entry has a String name and a class (see below)
@SharpComponent(
modules= {GithubServiceModule.class, PicassoModule.class},
sharpDependencies=MyApplication.class,
//dependencies=SomeDaggerComponent.class,
scope=MyCustomScope.class,
provides= {GithubService.class, Resources.class},
providesNamed= {
@NamedPair(aName="myPicasso", aClass=Picasso.class),
@NamedPair(aName="appContext", aClass=Context.class),
@NamedPair(aName="activityContext", aClass=Context.class)
}
)
publicclassMyFragmentextendsFragment {
...
}The code above would generate the following component
@Component(
modules= {GithubServiceModule.class, PicassoModule.class},
dependencies= {SharpMyApplicationComponent.class}
)
@MyCustomScopepublicinterfaceSharpMyFragmentComponent {
MyFragmentinject(MyFragmentthisClass);
GithubServiceprovideGithubService();
ResourcesprovideResources();
@Named("myPicasso")
PicassoprovidePicasso_myPicasso();
@Named("appContext")
ContextprovideContext_appContext();
@Named("activityContext")
ContextprovideContext_activityContext();
}