Dagger 2 Tutorial For Android: Advanced
In this tutorial, you’ll learn about the advanced concepts of Dagger. You’ll learn about component lifecycles, @Binds, and component builders and factories.
Version
- Kotlin 1.3, Android 4.1, Android Studio 3.5

Dagger is arguably the most used Dependency Injection, or DI, framework for Android. Many Android projects use Dagger to simplify building and providing dependencies across the app. It gives you the ability to create specific scopes, modules, and components, where each forms a piece of a puzzle: The dependency graph.
Unfortunately, Dagger can’t solve every problem, and it’s not easy to learn. It has many features you can use in many ways depending on the use case.
The trick here is to think of Dagger not as a DI framework but as a code generator tool that needs to know how to create instances of certain classes. Then you, as a developer, tell Dagger how to build and connect them.
As you may know, Dagger revolves around the use of annotations, which help it read and generate all the code it needs to work. All the different annotations are simply a way of telling Dagger what it doesn’t know to achieve its goal and create the code you otherwise would have to write yourself.
In this tutorial, you’ll learn:
- How to use
@Singleton
and what it really means. - The concept of the lifecycle of a
@Component
. - When and how to use
@Binds
. - When to use
@Component.Builder
and@Component.Factory
.
Getting Started
Download and unzip the materials by clicking the Download Materials button at the top or bottom of this tutorial. Open the project using Android Studio 3.5 or greater and then run it. You should see something like this:

RwNews App
As you can see, it’s a basic app that displays a list of news items, allows the user to select one and displays its content. However, in this context, the app’s functionality isn’t as important as the internal works! This is why when building and running the app, you may not see visual changes, but the internal structure and performance will indeed be different! :]
Taking a Closer Look
If you look at the project structure in Android Studio, you’ll notice a classic MVP architectural pattern implementation with the definitions as in the following UML class diagram:
The diagram only displays the classes that are useful in terms of dependencies. It’s important to understand what kind of dependencies Dagger can manage. In the following diagram, you’ll see which dependencies you’ll provide through Dagger:
The dotted line with the open arrow represents the dependency between two definitions. The previous diagram shows that NewsDetailFragment
depends on the NewsDetailPresenter
. You can also say that NewsDetailFragment
uses the NewsDetailPresenter
.
Interface inheritance is a special type of dependency. It describes the relation between a class and one of the interfaces it implements.
In the previous diagram, you can see that the NewsDetailPresenterImpl
is an implementation, or realization, of the NewsDetailPresenter
. Futhermore, the same type of a relation occurs between the NewsListPresenterImpl
and the NewsListPresenter
.
Using interfaces can help you achieve abstraction since you can depend on the interface, rather than the concrete implementation. This allows you to change the implementation completely, while the external API stays the same.
You can also see that the NewsListFragment
and NewsDetailFragment
don’t depend directly on the NewsRepository
but through a specific presenter implementation. With that in mind, the MemoryNewsRepository
is the only concrete implementation of NewsRepository
, so you’ll use it in both of the presenter implementations: NewsListPresenterImpl
and NewsDetailPresenterImpl
.
Finally, you can see that the full app depends on the common module containing some general-purpose classes and interfaces.
How Can Dagger Help?
This is a small project, but even now, organizing dependencies in a performant way might be difficult. At this point, it’s important to repeat what Dagger is: A tool for generating code to manage dependencies between different objects. To do this it needs to:
- Understand the dependency graph.
- Create instances of the dependencies and the end objects to inject.
- Execute the injection.
Understanding the Dependency Graph
The first step of setting up the Dependency Graph is to read out the structure of all the classes and dependencies you need to provide and use. Dagger does this first step using reflection during the build phase of the project. For instance, look at the signature of the constructor of the NewsDetailPresenterImpl
:
class NewsDetailPresenterImpl(
private val newsRepository: NewsRepository // HERE
) : BasePresenter<NewsModel, NewsDetailView>(),
NewsDetailPresenter {
- - -
}
You can see that the NewsDetailPresenterImpl
needs a reference to an object of type NewsRepository
. This means that to create an instance of NewsDetailPresenterImpl
, you need an object of type NewsRepository
: The former type depends on the latter. You’ll repeat the process for all classes and tell Dagger how to create a graph of dependencies.
What Object To Inject
To create an instance of the NewsDetailPresenterImpl
class, Dagger needs to know how to create an object of the NewsRepository
type. But it requires more information from you because this is an interface and you can’t simply instantiate it and use it. To accomplish the second task, you need to provide a @Module
whose responsibility is to give Dagger the information about the specific class to instantiate for a specific type:
@Module
class AppModule {
// 1
@Provides
fun provideNewsListPresenter(repo: NewsRepository): NewsListPresenter =
NewsListPresenterImpl(repo)
// 2
@Provides
fun provideNewsDetailPresenter(repo: NewsRepository): NewsDetailPresenter =
NewsDetailPresenterImpl(repo)
// 3
@Provides
fun provideRepository(): NewsRepository = MemoryNewsRepository()
}
With the previous code, you tell Dagger that:
- It should use a
NewsListPresenterImpl
when injecting aNewsListPresenter
instance. - The implementation for the
NewsDetailPresenter
is aNewsDetailPresenterImpl
instance. - You want to use a
MemoryNewsRepository
as an implementation of theNewsRepository
.
You’re actually doing more: You’re creating the instances of the required classes as return values of methods annotated with @Provides
. What Dagger does for you is managing the parameter of type NewsRepository
passing the appropriate reference in the component graph creation phase.
Defining Inject Targets
Now Dagger knows how to create the dependency graph, but it doesn’t know what to do with it. To command Dagger to use the dependencies, you have to define a @Component
. Its responsibility is to expose objects you want, from the dependency graph, and to inject those dependencies to target classes.
Dagger supports all three types of injection: Constructor, field and method injection.
You should use constructor injection the most because it allows you to set all the dependencies for an object when you create it. This is the type of injection you used for the NewsDetailPresenterImpl
class.
Sometimes this isn’t possible because you don’t have direct control over the creation of the instance of a class. This is the case of classes like Activity
and Fragment
whose lifecycle is the responsibility of the Android environment. In this case, you use the field injection, which injects dependencies into a class field, like so:
class NewsListFragment : Fragment(), NewsListView {
// 1
@Inject
lateinit var newsListPresenter: NewsListPresenter
private lateinit var recyclerView: RecyclerView
private lateinit var newsListViewAdapter: NewsListViewAdapter
private val newsListModel = NewsListModel(emptyList())
- - -
}
However, Dagger won’t inject the presenter, even though you’ve annotated it. It forces you to define a @Component
and inject to the target class manually. So to continue the setup, you need to add both the module and inject functions to the component, like so:
@Component(modules = [AppModule::class]) // 1
interface AppComponent {
fun inject(frag: NewsListFragment) // 2
fun inject(frag: NewsDetailFragment)
}
There are two important things to note here:
- Each component can only provide dependencies from the modules assigned to it.
- You need to declare each target injection class as a function with the parameter of the type of that class. In this case, the
inject()
functions represent this, but you can essentially name them whatever you want. This is just the convention.
You can also include modules within other modules, like a composition of functions. Then, once you add one module to a component, you add all those included in that composition. The syntax for doing so would be the following:
class SomeOtherModule
@Module(includes = [SomeOtherModule::class])
class AppModule
Because your project and setup are fairly simple, you don’t need multiple modules, to separate dependencies by their layers or types, however, it’s useful to know how to apply the separation when you encounter more complex projects! Move on to the last step of the setup! :]
Finally, you have to add the following code in one of the lifecycle methods of the target injection classes. For example, you can do so in onAttach()
, in fragments:
override fun onAttach(context: Context) {
// HERE
DaggerAppComponent.create().inject(this)
super.onAttach(context)
}
You call inject()
on the instance of the AppComponent
implementation which Dagger creates for you.
After calling inject()
, Dagger guarantees to inject the proper reference for all the fields with @Inject
, if they exist in the dependency graph. If they’re missing from the graph, you’ll get a compile-time error telling you which dependency is missing and where.
Scope Management
Open MemoryNewsRepository
, which is an implementation of NewsRepository
. You’re creating the data for the app within init()
. Init should run once per class initialization.
But when, and how many times, does that initialization really happen? Because this is a repository, and you’re using it to fetch data from some entity, it typically should be unique in the app.
Check if the repository is indeed initialized once. Open the NewsListPresenterImpl
. There you’ll see a log message as follows:
class NewsListPresenterImpl(
private val newsRepository: NewsRepository
) : BasePresenter<NewsListModel, NewsListView>(),
NewsListPresenter {
override fun displayNewsList() {
Log.i(TAG, "In NewsListPresenterImpl using Repository $newsRepository") // LOG
val newsList = newsRepository.list()
view?.displayNews(NewsListModel(newsList))
}
}
Run the app, select a news item from the list, go back and then select another news item. Open Logcat and filter the logs using AdvDagger as the tag. Notice a log similar to the following, although you’ve simplified it by removing the full package and time information:
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0 // SAME
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@464edaa // DIFFERENT
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0 // SAME
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@99c4f98 // DIFFERENT
As you can see, every time Dagger injects a different instance of the NewsRepository
. Because of the implementation of the MemoryNewsRepository
, this means the initialization happens every time Dagger injects the NewsRepository
.
This is something that shouldn’t happen. It adds more overhead to your app’s memory and hinders the performance. You can improve that by making the repository unique.
Providing Singleton Values
You can bind a specific dependency to the lifetime of a component by using a @Scope
. The first scope you usually meet when learning about Dagger is @Singleton
.
Open the AppModule
and update it by adding @Singleton
to the the MemoryNewsRepository
provider as follows:
// Other imports
import javax.inject.Singleton // HERE
@Module
class AppModule {
- - -
@Provides
@Singleton // HERE
fun provideRepository(): NewsRepository = MemoryNewsRepository()
}
You’ll also need to import the related package at the beginning of the class. If you try building the app you’ll get the following error:
e: ...AppComponent.java:7: error: [Dagger/IncompatiblyScopedBindings] com.raywenderlich.rwnews.di.AppComponent (unscoped) may not reference scoped bindings:
This happens because you define the NewsRepository
implementation in the AppModule
class, which contains information that the AppComponent
uses to create the instances of its dependency graphs. If you annotate its @Provides
method with @Singleton
you assign it a scope that the @Component
must know to understand when to create its instance.
Head over to the AppComponent
and add @Singleton
under @Component
:
@Component(modules = [AppModule::class])
@Singleton // HERE
interface AppComponent {
- - -
}
This scopes the repository to the lifetime of AppComponent
instances. Build and run, and once again open Logcat. The output is the same as the one before, where each instance has a different @xxxxxx hashcode.
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0 // SAME
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@adf2d9b // DIFFERENT
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0 // SAME
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@f5e63f1 // DIFFERENT
This happens because even though you’ve marked the @Component
and the provider as @Singleton
, it doesn’t mean that Dagger will create only one instance of the class.
It’s your job to keep track of each component and its lifecycle. It’s time to learn how to do that.
Managing the @Component Lifecycle
What does it mean to bind the lifecycle of an object to one of the @Component
s that manages it? It means that if you want a single instance of the MemoryNewsRepository
, you need to have a single instance of the AppComponent
, reusing it throughout your app.
The Android solution is to create a custom implementation of the Application
and store the component within.
Create a new class named InitApp in rwnews
and add the following code:
class InitApp : Application() {
// 1
private lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
// 2
appComponent = DaggerAppComponent.create()
}
// 3
fun appComp() = appComponent
}
This class which extends the Application
. In the code above, it does the following:
- Defines the
appComponent
, containing a reference to the instance which Dagger creates. - Creates the instance of the
AppComponent
usingcreate()
onDaggerAppComponent
. Remember that theDaggerAppComponent
is an implementation generated by Dagger once you build your project. - Defines
appComp()
to expose theappComponent
.
Next, you need to tell Android to use this definition into the app. Open AndroidManifest.xml
and set the .InitApp as the value for the android:name
attribute of the application
element.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.raywenderlich.rwnews">
<application
- - -
android:name=".init.InitApp"> // HERE
</application>
- - -
</manifest>
When you launch the app, Android creates a new instance of the custom Application
implementation and invokes onCreate()
on it. This creates an instance of the AppComponent
and stores it within InitApp
.
Now you can proceed to use and share the instance of the component in your target inject classes.
Sharing the @Component
Next, you need to access the same instance of the AppComponent
in every place you need it.
Open NewsListFragment.kt and replace the code from onAttach()
with the following:
class NewsListFragment : Fragment(), NewsListView {
@Inject
lateinit var newsListPresenter: NewsListPresenter
- - -
override fun onAttach(context: Context) {
(context.applicationContext as InitApp) // HERE
.appComp().inject(this)
super.onAttach(context)
}
- - -
}
Here you’re getting the applicationContext
and casting it to InitApp
to call appComp()
which returns the reference to the single AppComponent
within InitApp
.
Do the same in NewsDetailFragment.kt:
class NewsDetailFragment : Fragment(), NewsDetailView {
- - -
override fun onAttach(context: Context) {
(context.applicationContext as InitApp)
.appComp().inject(this)
super.onAttach(context)
}
- - -
}
Now build and run the app and open a news item once or twice. Check the log in output. It should be similar to the following:
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@82183c0
I/AdvDagger: In NewsListPresenterImpl using Repository MemoryNewsRepository@82183c0
I/AdvDagger: In NewsDetailPresenterImpl using Repository MemoryNewsRepository@82183c0
The instance of the NewsRepository
is always the same. Remember, this isn’t happening because of the @Singleton
annotation, but because the instance of the AppComponent
you’re using for injection is the same and precisely the one you stored into the InitApp
class.
Using @Binds
The current app works, but you can apply optimizations to reduce the code generation time, as well as the quantity of the generated code. You can rely on @Binds
instead of @Provides
to do this.
Open the AppModule.kt and look at the following definition:
@Module
class AppModule {
- - -
@Provides
@Singleton
fun provideRepository(): NewsRepository = MemoryNewsRepository()
}
provideRepository()
informs Dagger that the implementation to use for the NewsRepository
is MemoryNewsRepository
. You’re doing some work here because you’re the one that’s creating the instance, and defining the provider contract.
You can avoid this, and delegate the creation of the implementation to Dagger, by using @Binds
. It lets you bind a specific interface to the class constructor for the implementation, hence the name.
Delete provideRepository()
from the AppModule
and create a new file named NewsRepositoryModule.kt within the di package. Then add this code to it:
@Module
abstract class NewsRepositoryModule {
@Binds
abstract fun provideRepository(repoImpl: MemoryNewsRepository): NewsRepository
}
This is a new @Module that tells Dagger the class bound to the NewsRepository
is MemoryNewsRepository
. You do this by defining an abstract method which accepts a single parameter of the implementation type and has the interface type as return type. Because the method is abstract the class is also abstract.
AppModule
class in place of the one above. In that case, the class must be abstract, and Dagger forces you to make the other provide methods static.
In Kotlin, you’d have to use the @JvmStatic annotation for provide methods into a companion object. You’ll learn how to do this later.
Next, open the AppComponent
and add the module to modules
in @Component
. Its definition becomes the following:
@Component(modules = [AppModule::class, NewsRepositoryModule::class])
@Singleton
interface AppComponent {
- - -
}
There’s one last step to finish binding the interface to the implementation.
Binding Dependencies
As the last step, you need to remember what you read at the beginning of this tutorial. Dagger needs to know how to create instances.
If you build the app at this point, Dagger will complain that it can’t create an instance of the MemoryNewsRepository
because it doesn’t know how to yet. You still need to annotate the MemoryNewsRepository
‘ constructor with @Inject
. So, open it and add change the class signature to this:
@Singleton
class MemoryNewsRepository @Inject constructor() : NewsRepository {
- - -
}
You also need to use @Singleton
because it’s a property of the specific implementation and not of the NewsRepository
abstraction. For this reason, using @Singleton
with @Binds
is sometimes considered bad practice.
Now build and run the app and check that it works as expected!

RwNews App
Improving Binds
Dagger introduced @Binds
as a more compact way of declaring the relation between an abstraction type and its implementation. It lets you delegate the creation of the actual implementation to Dagger as you did with the MemoryNewsRepository
. More importantly, it reduces the code generation time along with the number of lines of generated code.
You might argue that you had to create a new class for this as a consequence of the problem of having @Provides
methods within an abstract class. This way it seems like you’re adding extra code, to reduce code, which doesn’t make much sense, right? Well, having to declare a small module was simple, and the performance gains behind are worth it, once you start adding more and more dependencies in your project.
But if you still want to avoid having to create a module for @Bind
annotated providers, then you can use a different approach, as noted below:
@Module
// 1
abstract class AppModule {
// 2
@Module
companion object {
// 3
@JvmStatic
@Provides
fun provideNewsListPresenter(repo: NewsRepository): NewsListPresenter =
NewsListPresenterImpl(repo)
// 3
@JvmStatic
@Provides
fun provideNewsDetailPresenter(repo: NewsRepository): NewsDetailPresenter =
NewsDetailPresenterImpl(repo)
}
// 4
@Binds
abstract fun provideRepository(repoImpl: MemoryNewsRepository): NewsRepository
}
Now the AppModule
is an abstract class and you had make some relatively big changes:
- The
AppModule
is nowabstract
. - You need a
companion object
for the definitions of@Provides
. It’s also important to annotate this object with@Module
as well. - Providers also annotated with
@JvmStatic
which is a Kotlin annotation useful if you want to make this functionstatic
, in the meaning of Java, in the companion object. - Now you can use
@Binds
here.
Before building you need to clean what you did previously. Delete NewsRepositoryModule.kt and remove NewsRepositoryModule::class
from the AppComponent
.
Now, build and run. Check that everything is working as expected.

RwNews App
Hidden Power of @Binds
The true power of both @Binds
and static @Provides
is that Dagger doesn’t generate factory classes which wrap those functions. This is the part about generating less code and increasing performance. Not only does it increase performance at build-time, but it also increases the runtime performance because Dagger is no longer allocating extra classes for each component you create.
Finally, by using @Inject
and @Binds
, you’ve abstracted away the creation of the repository dependency. This means that if you change the constructor parameters in the MemoryNewsRepository
, you won’t have to change the provider function. It’ll update automatically, because of the @Inject
.
If you did this for all the dependencies, you could freely update the constructors by adding or removing parameters, changing their order, and you wouldn’t have to do the extra work of updating the provider/factory functions.
The @Component.Builder Interface
Look at the last implementation of the AppModule
. You can see that you needed to do magic with the companion object and static methods because of the use of @Binds
which required the annotated method to be abstract.
But what if you want to provide the instance for the NewsRepository
type when you instantiate the AppComponent
? To do this, change the implementation of the AppModule
class like this:
@Module
class AppModule(
// 1
private val newsRepository: NewsRepository
) {
// 2
@Provides
fun provideNewsListPresenter(): NewsListPresenter = NewsListPresenterImpl(newsRepository)
// 2
@Provides
fun provideNewsDetailPresenter(): NewsDetailPresenter = NewsDetailPresenterImpl(newsRepository)
}
See the following new steps:
- The
AppModule
now defines a constructor with a parameter of the typeNewsRepository
. - The same is then used to create the instances that
@Provides
annotated methods return. The methods don’t have any parameters now.
If you build the application now, you’ll get an error in InitApp
, saying DaggerAppComponent.create()
doesn’t exist.
Providing Parameterized Dependencies
If the @Module
used by a @Component
needs a parameter, Dagger doesn’t generate create()
. It instead generates an implementation of the Builder pattern which requires you to provide the parameterized dependencies. Change the code in the InitApp
like this:
class InitApp : Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent
.builder() // 1
.appModule(AppModule(MemoryNewsRepository())) // 2
.build() // 3
}
fun appComp() = appComponent
}
As you can see:
- The
DaggerAppComponent
that Dagger provides now has abuilder()
which returns an implementation of aComponent.Builder
. - You create an instance of the
MemoryNewsRepository
you need, to create the instance of theAppModule
. You then pass to theAppComponent
builder the createdAppModule
usingappModule()
. - The last method to invoke in the Builder implementation is called
build>()
. It returns theAppComponent
implementation.
In this case, you don’t need the @Singleton
annotation anymore. This is because you’re responsible of the creation of the MemoryNewsRepository
class which is then used by the AppComponent
any time it needs it.
Remove @Singleton
from the MemoryNewsRepository
and AppComponent
as in these definitions:
class MemoryNewsRepository : NewsRepository {
- - -
}
@Component(modules = [AppModule::class])
interface AppComponent {
- - -
}
Build and run the app. It now works as expected, reusing the same instance of MemoryNewsRepository
in all the fragments.

RwNews App
On one hand, you own the MemoryNewsRepository
, so passing it in as a parameter didn’t do much. On the other hand, this is how you pass the reference to the Context
, the Resources
, or any other runtime-created dependency you don’t own in Andriod.
Improving Parameterized Dependencies
In the previous code, you created the MemoryNewsRepository
in the InitApp
and passed it to the builder of the AppComponent
encapsulating it within an instance of the AppModule
.
You can do better and pass only what Dagger really needs: The instance of the MemoryNewsRepository
. To do this, change the current code in the AppComponent.kt to get the following implementation:
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(frag: NewsListFragment)
fun inject(frag: NewsDetailFragment)
// 1
@Component.Builder
interface Builder {
// 2
@BindsInstance
fun repository(repo: NewsRepository): Builder
// 3
fun build(): AppComponent
}
}
There are many important things to note here:
- You created an inner interface annotated with
@Component.Builder
. The name is usuallyBuilder
but it’s not important. - The interface needs to define some operations similar to the ones you created for
@Binds
. Each of them must have a single parameter of the type of the object you need to inject and must have the same interface as return type.
This allows for chaining of such methods. Each of these methods must be annotated with@BindsInstance
. - Finally, need to define a method whose name must be
build
which must have the component as the return type. In this case, the type isAppComponent
.
As you can see, there are many musts you need to follow.
Now you open the AppModule
and remove the parameter from the constructor getting the following implementation:
@Module
class AppModule {
@Provides
fun provideNewsListPresenter(newsRepository: NewsRepository): NewsListPresenter =
NewsListPresenterImpl(newsRepository)
@Provides
fun provideNewsDetailPresenter(newsRepository: NewsRepository): NewsDetailPresenter =
NewsDetailPresenterImpl(newsRepository)
}
You kinda went all the way back to square one. Such a déjà vu. :]
To build and run the app, you need to change the way you create the AppComponent
within InitApp
like this:
class InitApp : Application() {
- - -
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent
.builder()
.repository(MemoryNewsRepository()) // HERE
.build()
}
- - -
}
Dagger created the repository()
for the Builder
which lets you pass the MemoryNewsRepository
directly. Now build and run the project and the app still runs successfully! :]

RwNews App
Making Dagger Work for You Again
The previous implementation for the AppModule
was a déjà vu because it’s very similar to one of the first implementations. But now you also know how to use @Binds
! Change the AppModule
class to this to re-implement @Binds
:
@Module
abstract class AppModule {
@Binds
abstract fun provideNewsListPresenter(newsRepository: NewsListPresenterImpl): NewsListPresenter
@Binds
abstract fun provideNewsDetailPresenter(newsRepository: NewsDetailPresenterImpl): NewsDetailPresenter
}
This isn’t enough. While Dagger knows what classes to use as implementation of the NewsListPresenter
and NewsDetailPresenter
, it doesn’t know how to create an instance of NewsListPresenterImpl
and NewsDetailPresenterImpl
.
You already know the solution: @Inject
. Add the annotation to the constructors like in the following code:
class NewsDetailPresenterImpl @Inject constructor(
private val newsRepository: NewsRepository
) : BasePresenter<NewsModel, NewsDetailView>(),
NewsDetailPresenter {
- - -
}
and
class NewsListPresenterImpl @Inject constructor(
private val newsRepository: NewsRepository
) : BasePresenter<NewsListModel, NewsListView>(),
NewsListPresenter {
- - -
}
Build and run the app as usual.

RwNews App
Using the @Component.Factory Interface
Like the Builder, the Factory method is a creational GoF pattern. That means it defines some way of creating instances of a specific class. While the former provides you some methods in to pass what you need, the latter provides you a single method with multiple parameters.
The former defines a build()
that the latter doesn’t need. The same difference happens when you use them with Dagger. To prove this, change the AppComponent.kt to the following:
@Component(modules = [AppModule::class])
interface AppComponent {
fun inject(frag: NewsListFragment)
fun inject(frag: NewsDetailFragment)
// 1
@Component.Factory
interface Factory {
// 2
fun repository(@BindsInstance repo: NewsRepository): AppComponent
}
}
Here you can see two main differences:
- The inner interface is now annotated with
@Component.Factory
. - The interface defines a single method which has the
AppCompomnent
as return type. The parameter is of the type you need to pass and is annotated with@BindsInstance
.
In this case, the factory method contains only one parameter but it could have many. You can see the different generated code in the InitApp
class where the creation of the AppCompomnent
has to be like this:
class InitApp : Application() {
- - -
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent
.factory() // 1
.repository(MemoryNewsRepository()) // 2
}
- - -
}
As you can see, Dagger creates a factory
method for you which exposes the repository()
you can invoke to pass the missing dependencies. Build and run the app.

RwNews App
You’ve now covered many ways you can build dependencies in Dagger! :]
Where to Go From Here
You can download the final result using the Download Materials button at the top or bottom of this tutorial.
In this tutorial, you configured Dagger to manage DI in several ways, depending on what information you provided and how they can be used to manage dependencies, change code generation performance and runtime dependency fetching.
You’re a Dagger master now, but you still need to learn one more step: How to manage dependencies between different @Component definitions with different @Scope
. You’ll learn that in the second part of this tutorial! :]
I hope you found this helpful! If you have any comments or questions, feel free to join in the forum below.
Comments