Vandolf Estrellado
Aug 28, 2017 · 2 min read

Mahan Rad, your question is answered in the official dagger docs.

official dagger docs

As the docs states, “because the AndroidInjector.Builderimplementation that is generated by Dagger does retain an instance of the Activity/Fragment/etc that is being injected, it is a compile-time error to apply a scope to the methods which provide them.” To verify this, checkout the branch before the project was migrated over to using @ContributesAndroidInjector. Add @PerActivity to the mainActivityInjectorFactory in the AppModule so that it would look like this:

...
abstract class AppModule {

@PerActivity
@Binds
@IntoMap
@ActivityKey(MainActivity.class)
abstract AndroidInjector.Factory<? extends Activity>
mainActivityInjectorFactory(MainActivitySubcomponent.Builder builder);
...
}

Rebuilding the project would result in the following compile-time error:

error: dagger.android.AndroidInjector.Factory bindings should not be scoped. Scoping this method may leak instances of android.app.Activity.

This error cannot be suppressed by @SuppressWarnings(“dagger.android.ScopedInjectoryFactory”) (as mentioned by the docs) because we are using AndroidInjector.Builder, which retains an instance of the Activity/Fragment.

So how does this answer your question? Keep in mind that @ContributesAndroidInjector is just a shortcut for using @Subcomponents, AndroidInjector, and AndroidInjector.Builder (having no other methods or supertypes) with AndroidInjector.Factory. The underlying generated code is the same.

Note: The @PerActivity annotation in the injector factory when using @ContributesAndroidInjector corresponds to the scope of the @Subcomponent when using the AndroidInjector.Factory routine. It is not the scope of the injector factory itself. The injector factory is, as the docs states, stateless.

I’ll answer your questions more directly.

“This basically means that if I perform injection (AndroidInjection.inject(this)) multiple times, I am entitled to get the same injected instance.”

This is not true when using AndroidInjection from the dagger.android framework.

“…why is MainActivity is injected with a different instance eachtime the “.inject()” method is invoked?”

Due to the stateless nature of the injector factory as discussed above. A new injector is used to inject the Activity/Fragment each time AndroidInjection.inject is called. You can verify this if you step-through the generated code.

The real question is why the Activity/Fragment would need to be injected (via AndroidInjection.inject) more than once throughout its lifecycle? This, to me, sounds like a code smell that should be fixed using Java best practices and design patterns instead of a dependency injection framework. I could be missing something though…

)

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade