android / architecture-samples

A collection of samples to discuss and showcase different architectural tools and patterns for Android apps.
Apache License 2.0
44.49k stars 11.65k forks source link

when does @Inject method in PresenterImpl execute (todo-mvp-dagger) #125

Closed mawenge closed 8 years ago

mawenge commented 8 years ago

in mvp dagger example, the presenter object was injected in activity, and in presenterImpl, there is a method "setupListeners"

@Inject void setupListeners() { mStatisticsView.setPresenter(this); }

the method make the View have reference of presenter, and this is a @Inject method.

I don't know when does this method execute and by who?

saulmm commented 8 years ago

That method is executed by Dagger2 using a type of injection known as method injection. Currently, dagger supports three different types of injections:

Field injections:

This type of injection is performed when we have the @inject annotation in a field, i.e: @Inject TasksPresenter mTasksPresenter;. This is commonly used when our project requirements don't make us easy to use the constructor for injecting dependencies (activities, fragments on android for instance).

Constructor injections

This approach uses the constructor for injecting dependencies, this is the old definition of dependency injection. When Dagger2 finds a constructor tagged with the @inject annotation, it tries to create its dependencies based on another @inject annotations around the constructors, or modules who create these dependencies.

    @Inject
    TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
        mTasksRepository = tasksRepository;
        mTasksView = tasksView;
    }

Method injection

This is the answer to your question, this final approach it uses methods annotated with the @inject annotation to injects all its parameters with dependencies of the graph. The use of this injection is useful for receiving an instance of the class where it lives, since is called right after its constructor (when an instance is created), in that way we are able to pass a reference of the created presenter to the view. That's an elegant and a nice way to inject presenters into views in a model-view-presenter pattern.

    /**
     * Method injection is used here to safely reference {@code this} after the object is created.
     * For more information, see Java Concurrency in Practice.
     */
    @Inject
    void setupListeners() {
        mTasksView.setPresenter(this);
    }
Rainer-Lang commented 8 years ago

@saulmm thank you for this great explanation.

mawenge commented 8 years ago

@saulmm thanks for your reply, and I also find that for a class, only with constructor injection will make the @inject method execute after constructor. if the PresenterImpl was instantiated by using a @Provide method in a module, like this

`@Provide
void providePresenter(TasksRepository tasksRepository, TasksContract.View tasksView) {
    return new TasksPresenter(tasksRepository,  tasksView);
}`

not @inject for constructor, @Inject TasksPresenter(TasksRepository tasksRepository, TasksContract.View tasksView) { mTasksRepository = tasksRepository; mTasksView = tasksView; } in this case ,setupListeners() will not execute,.

Am I right?

saulmm commented 8 years ago

Yes I think so, the method injection will be performed by the MemberInjector class which understands that if you are able to create your instances via @Provide you don't need a method injection.

  /**
   * Injects dependencies into the fields and methods of {@code instance}. Ignores the presence or
   * absence of an injectable constructor.
   *
   * <p>Whenever the object graph creates an instance, it performs this injection automatically
   * (after first performing constructor injection), so if you're able to let the object graph
   * create all your objects for you, you'll never need to use this method.
   *
   * @param instance into which members are to be injected
   * @throws NullPointerException if {@code instance} is {@code null}
   */

Sorry for the late response @mawenge

JoseAlcerreca commented 8 years ago

Closing this one, feel free to open a new issue if you have further questions.