Android Architecture Blueprints “todo-mvp-dagger”, where is @Provides for TasksRepository?
Check out the Android architecture blueprint “todo-mvp-dagger” here: https://github.com/googlesamples/android-architecture .
I’m trying to understand the implementation of Dagger2, but I can’t seem to figure out how they get Dagger2 to provide a TasksRepository.
They have @Provides
for “provideTasksLocalDataSource” and “provideTasksRemoteDataSource”, but where is the actual TaskRepository?
In the TodoApplication class, they have this:
@Inject
TasksRepository tasksRepository;
How does it inject it anywhere without @Provides?
I get this error if I try to use the same method in my own application:
cannot be provided without an @Provides- or @Produces-annotated method
So I looked around at the Blueprint code, but I couldn’t see how they did it themselves. Are there some tricks to keep them free of @Provides
? It will definitely build, so they have somehow bypassed it.
Someone has asked the same question on an actual github page, but there is no answer at the time of writing. https://github.com/googlesamples/android-architecture/issues/561 .
I’m working on the latest commit, and at the time of writing it is “082bd72d62472f9caadd2979046067fb928bbfef”.
Solution
In the repository you mentioned, Dagger 2 knows how to inject TasksRepository
through constructors marked with @Inject
. From source :
@Inject
TasksRepository(@Remote TasksDataSource tasksRemoteDataSource,
@Local TasksDataSource tasksLocalDataSource) {
mTasksRemoteDataSource = tasksRemoteDataSource;
mTasksLocalDataSource = tasksLocalDataSource;
}
Since the constructor is annotated as @Inject
, Dagger 2 will attempt to inject TasksRepository
with constructors like TodoApplication
Since TasksDataSource
has been binded, there is enough information in the TasksRepositoryModule
for Dagger 2 to perform an injection without the additional burden of @Provides
or @Binds
methods.
Similarly, you can do the following:
class Foo {
private final Bar bar;
@Inject
Foo(Bar bar) {
this.bar = bar;
}
}
class Bar {
@Inject
Bar() {}
}
class Activity extends AppCompatActivity {
@Inject Foo foo;
}
And Dagger 2 will be able to inject into Foo
AppCompatActivity.Why
?
- Dagger 2 knows how to build
a Bar
object (by calling an empty constructor). - Dagger 2 creates an instance of
Foo
knowing that it must use a single parameter Bar. using a constructor annotatedas @Inject
Foo
has no other dependencies, in other words, a complete object graph is available.