Java – Android Architecture Blueprints “todo-mvp-dagger”, where is @Provides for TasksRepository?

Android Architecture Blueprints “todo-mvp-dagger”, where is @Provides for TasksRepository?… here is a solution to the problem.

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?

  1. Dagger 2 knows how to build a Bar object (by calling an empty constructor).
  2. Dagger 2 creates an instance of Foo knowing that it must use a single parameter Bar. using a constructor annotated as @Inject
  3. Foo has no other dependencies, in other words, a complete object graph is available.

Related Problems and Solutions