Android Presenter To Activity Using Guice

In a prior post I talked about how to unit test android applications. I made some references to wiring up an Activity with a presenter, but I didn’t really show how I was doing that.

I got some requests to show some sample code, so I thought I would explain what I was doing here and see if anyone had better suggestions.

Roboguice

To make it easier to unit test and to decouple my system as much as possible, I am using a dependency injection framework called Roboguice. It is basically the Google Guice framework that is ported to Android and adds some Android specific functionality.

One challenge you will most likely first encounter when working with Roboguice is that a presenter is going to need a reference to the Activity class that is going to represent its view. Since the Activity class has to create the presenter, this presents a dependency injection challenge.

We can’t just ask for a presenter from our container and have it auto-resolve the dependency on the Activity. (That is we can’t rely on constructor injection in this case.)

Setter injection to the rescue

One thing we can do, is use setter injection instead of constructor injection to inject the other references our presenter will need.

Guice provides us with an easy way to perform setter injection after we have created the object. I use this technique to make sure that I can pass my activity into the presenter and still have the benefits of having the other dependencies injected into the presenter.

This code is creating an instance of my presenter which holds a reference to the Activity, or view, it is manipulating. Then Guice injects dependencies using the module I created into any properties that are annotated with @Inject.

It’s not exactly pretty, but Android applications are really a loosely coupled sets of Activities which are the entry point into your code. It makes it very difficult to create a MVP type of framework that we might be used to.

If you know of a better way than what I am doing please let me know, and if you have any questions or suggestion, I’m always glad to hear them or help if I can.

As always, you can subscribe to this RSS feed to follow my posts on Making the Complex Simple. Feel free to check out ElegantCode.com where I post about the topic of writing elegant code about once a week. Also, you can follow me on twitter here.

Responses

The end result is pretty much the same for me, but I’ve been doing it a bit different. My presenters are constructor injected for all dependencies other than the activity. My Activity has an injected field for the presenter:

@Inject private MainPresenter presenter;

Then, I have a base presenter that all presenters inherit from that has this method on it:

public void InitializeWith(IMainActivity activity) { }

My C# past is showing with the interface name, isn’t it? Anyway, my activities all have an interface they implement, and this method gets called in onCreate in the Activity:

presenter.InitializeWith(this);

From there, the presenter has a reference to the activity and can finish up the work.

Very nice. I like that approach also.
If I understand you correct you are just doing the opposite. (Basically using constructor injection for all the dependencies besides the Activity, and setting that manually vs what I am doing using manual constructor for the Activity and setter injection for other dependencies.)
I originally had some base classes / interfaces, but I found they weren’t really serving any purpose, so I got rid of them. Are you using your base classes for more than InitializeWith?
I also use IMyInterface in Java, I think it is important to know if something is an interface or class.

good injection practice:
@Inject
is bad practice,…
the code being injected should not know it being injected !
Warning: coupling 😛

on the side note: making a MVC/MVP or whatever, makes little sense.
Android GUI is already a good framework!
you GUI should not large to the extend you need a framework to handle it!
if so, YOU have a huge problem by design that you have too much or too complicated, most likely not complaint with native behavior app.
DO NOT do that!