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'
}
@Module
public class MyModule {
@Provides
Object myObject() {
return new Object();
}
}
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, ...}
)
public class MyApplication extends Application {
}
After building, two files are generated:
SharpMyApplicationComponent.java -- (Names is formed as: Sharp + Class Name + Component)
@Component
@SharpMyApplicationScope
public interface SharpMyApplicationComponent {
MyApplication inject(MyApplication thisClass);
}
SharpMyApplicationScope.java -- (Names is formed as: Sharp + Class Name + Scope)
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface SharpMyApplicationScope {}
@Module
public class MyModule {
@Provides
@SharpMyApplicationScope
Object myObject() {
return new Object();
}
}
@SharpComponent(
modules = MyModule.class
)
public class MyApplication extends Application {
private SharpMyApplicationComponent sharpComponent;
@Inject
Object injectedObject;
@Override
public void onCreate() {
super.onCreate();
// Name is: Dagger + Sharp + Class Name + Component
sharpComponent = DaggerSharpMyApplicationComponent.builder().build();
sharpComponent.inject(this);
Log.d("MyApplication", "onCreate: " + injectedObject.toString());
}
public SharpMyApplicationComponent getSharpComponent() {
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
)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
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
@SharpMainActivityScope
public interface SharpMainActivityComponent {
MainActivity inject(MainActivity thisClass);
}
SharpMainActivityScope.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface SharpMainActivityScope {}
@SharpComponent(
modules = MyModule.class,
provides = Object.class // Array of dependencies can be provided as {A.class, B.class, etc.}
)
public class MyApplication extends Application {
...
}
@SharpComponent(
sharpDependencies = MyApplication.class // The class(es) annotated with @SharpComponent
)
public class MainActivity extends AppCompatActivity {
@Inject
Object myObject;
@Override
protected void onCreate(Bundle savedInstanceState) {
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)
}
)
public class MyFragment extends Fragment {
...
}
The code above would generate the following component
@Component(
modules = {GithubServiceModule.class, PicassoModule.class},
dependencies = {SharpMyApplicationComponent.class}
)
@MyCustomScope
public interface SharpMyFragmentComponent {
MyFragment inject(MyFragment thisClass);
GithubService provideGithubService();
Resources provideResources();
@Named("myPicasso")
Picasso providePicasso_myPicasso();
@Named("appContext")
Context provideContext_appContext();
@Named("activityContext")
Context provideContext_activityContext();
}