If you’ve been following this series, you already read about dependency injection basics on part 1 and Dagger fundamentals on part 2. This last part about Dagger and dependency injection Android is focused on scoped object graphs.

What’s the use of scoped graphs in Dagger?

When we instantiate Dagger singletons in application object graph, they live in memory until the app is destroyed. But there are some singleton dependencies that are useful only when another object is alive. A simple example is a view and its presenter. Most of times you will only use a presenter with an activity at the same time. In MVP, a presenter without a view is useless. We don’t need to keep it in memory after the activity is destroyed.

How to create a scoped graph?

It’s easy, we will add it to the application graph. I’m creating a module per activity. So let’s see an example in LoginActivity:

[java]

@Module(

injects = LoginActivity.class,

addsTo = AppModule.class

)

public class LoginModule {

private LoginView view;

public LoginModule(LoginView view) {

this.view = view;

}

@Provides @Singleton public LoginView provideView() {

return view;

}

@Provides @Singleton

public LoginPresenter providePresenter(LoginView loginView, LoginInteractor loginInteractor) {

return new LoginPresenterImpl(loginView, loginInteractor);

}

}

[/java]

Want to learn Kotlin? Check my free guide to create your first project in 15 minutes! GET THE FREE GUIDE

This module injects LoginActivity, because it needs to inject the presenter to the activity directly, not via constructor. It will be added to AppModule when be create the activity graph. Both things must be declared at @Module annotation.

As you can see, I added a new dependency to LoginPresenter. Its LoginInteractor will be injected from a new module called InteractorsModule. It’s a simple and standard module:

[java]

@Module(

library = true

)

public class InteractorsModule {

@Provides public FindItemsInteractor provideFindItemsInteractor() {

return new FindItemsInteractorImpl();

}

@Provides public LoginInteractor provideLoginInteractor() {

return new LoginInteractorImpl();

}

}

[/java]

Add it to AppModule as you previously did with DomainModule:

[java]

@Module(

injects = {

App.class

},

includes = {

DomainModule.class,

InteractorsModule.class

}

)

public class AppModule {

…

}

[/java]

Let’s create the object graph. It will be created by calling plus() to application graph and passing new modules. So I created this method in App:

[java]

public ObjectGraph createScopedGraph(Object… modules) {

return objectGraph.plus(modules);

}

[/java]

And now in Activity we inject the presenter instead of instantiating it, create the graph and inject the activity:

[java]

public class LoginActivity extends Activity implements LoginView, View.OnClickListener {

@Inject LoginPresenter presenter;

…

private ObjectGraph activityGraph;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_login);

…

activityGraph = ((App) getApplication()).createScopedGraph(new LoginModule(this));

activityGraph.inject(this);

}

@Override protected void onDestroy() {

super.onDestroy();

activityGraph = null;

}

…

}

[/java]

Set it to null in onDestroy so that it will be freed by garbage collector as soon as possible. Now you will have presenter, view and model injected using Dagger.

Conclusion

Dagger is a powerful tool, but its learning curve is larger than other libraries because it’s important that main concepts are embraced and that you understand why it is useful. I hope this set of articles helped you resolve most of difficulties you may find at the beginning.

I updated the code and created a BaseActivity that encapsulates the repetitive work of instantiating the scoped graph.

Dagger example at Github

If you have any doubts or think that another post will be useful to clarify any concept, please write a comment.

Like this: Like Loading...