Before touching the concept of scope and subcomponent, let’s go through some of the Dagger basics.
What is Dagger?
Dagger is a fully static, compile-time dependency injection framework for both Java and Android. It is created by Square and now maintained by Google.
Dagger 2 provides some annotations for implementing dependency injection.
@Inject annotation let us define an injection point that is injected during class instantiation. The injection can occur via three different mechanisms. This annotation provided by java.
- Constructor parameter injection
- Method initializer parameter injection
- Direct field injection
It’s an annotation that marks the class which provides dependencies. Consider AddressModule which provide Address dependency to the required place.
Here we use @Provides annotation which provides the dependency. @Provide annotation can be available in @Module or @ProducerModule.
The component is a bridge between generated code which is created by dagger library at compile time and dependencies. This interface is implemented to the generated class which tells dagger how to inject dependency.
Now we have to rebuild our project, so that dagger can create a dependency graph, after a successful build, it will create DaggerEmployeeManagerComponent which is generated class by the dagger.
Module annotated class is not always required. You can provide dependency without it. Module class help in organizing the related dependency together and makes code modular. I will show you how you can inject dependency without module class in below example.
So this is just a start before we can deep dive into scopes and subcomponent.
What is @Scope annotation and their responsibility?
I read many dagger related blogs and this annotation is a most underrated annotation. Whenever scope is named first thing comes into our mind is @Singleton which is provided by the dagger. As the name suggests an instance of an object created only once and stays there all the time. Code for singleton annotation is below.
Here we can see singleton is interface annotated by scope keyword and retention policy which is RUNTIME.
So scope responsibility is to ensure that variable created once a retained within scope, after defining the scope you don’t have to worry about creating object again and again.
Now, this is the right time to create a custom scope.
To explain more in detail I will show you one example.
In the above code snippet, I created two classes which contain information about EmployeeAddress and EmployeeContactDetails. To provide a dependency of employee information I created one Module EmployeeDetailModule. In EmployeeDetailModule I wrote two functions which returns EmployeeAddress while other returns EmployeeContactDetail with one twist, For EmployeeAddress I mentioned the EmployeeScope while EmployeeContactDetails is without any scope.
Our EmployeeComponent class is a component which provides methods to access Employee information at the desired place.
We want the dependency to inject at MainActivity. To achieve this I created a dependency graph using the following code.
Now I just logged the EmployeeAddress and EmployeeContactDetails three times to show the difference between objects which are annotated with EmployeeScope and object which are not annotated.
Here we can see that EmployeeAddres which is annotated with Employee scope points to the same object while EmployeeContactDetail is created every time. This is a power of scopes in Dagger world.
Now you are aware of scopes, take a long breath because we entering into the beautiful world of scopes and subcomponents, they can do wonders together.
What are Subcomponents?
Subcomponents are components that inherit and extend the object graph of a parent component. It’s a subset of the component, we can use subcomponent to separate object graph of an application into the subgraph. Custom scope plays an important role in defining an object validity within subcomponent.
An object which is present in subcomponent can have access to objects from their parent but objects within scope can’t be accessed outside.
In the above diagram, we can see that there is one main ApplicationComponent which will have dependencies which are required throughout the application, While there are two subcomponents which hold dependencies which are accessible to specific part of the application like (EmployeeActivity) or (OfficeActivity).
To understand more in detail lets check code and how to create subcomponents.
Here we have EmployeeModule which provide EmployeeDetail with EmployeeScope.
Now we created one a subcomponent which is an interface, with EmployeeScope. Now is the most important part, we mentioned annotation @Subcomponent with modules which will provide dependency, which is EmployeeModule. We created Subcomponent now we need the parent for this subcomponent. Let’s create one below.
We created one AppComponent which provides dependency for application scope. In an interface, we added function addEmployeeSubComponent() which takes EmployeeModule as an input and returns EmployeeSubComponent.
Above is Application class which will generate a dependency graph for application scope and accessible everywhere.
Below code will explain how to create a graph object for EmployeeSubComponent.
In Employee activity, we are creating subcomponent graph by accessing appComponent from application class and providing them EmployeeModule. Once we get employeeComponent we can ask to inject dependency by providing an instance of the activity. Like below.
Now we can access employeeDetail object. TADA!!!! We used subcomponent and custom scope to separate out object graph of an application into the subgraph.
Why use subcomponent and custom scope?
With normal, unscoped bindings, each user of an injected type may get a new, separate instance. But if the binding is scoped, then all users of that binding within the scope’s lifetime get the same instance of the bound type.
That’s it, folks!! If you reach till here means you guys are awesome. Please let me know where I can improve or am I doing wrong. If you guys like this blog give some claps :P.
Here is Github Link for the above code.