Advertisements
Posted by: jsonmez | August 19, 2010

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.

Here is some code showing my OnCreate method inside my activity.

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    setContentView(R.layout.pacemaker);

    this.presenter = new MainPresenter(this);
    Injector injector = Guice.createInjector(new PaceMakerModule());
    injector.injectMembers(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.

Here is what some of those presenter set methods look like:

@Inject
public void setSystemClock(ISystemClock systemClock)
{
     this.systemClock = systemClock;
}

@Inject
public void setRunSerializer(IRunSerializer serializer)
{
     this.runSerializer = serializer;
}

You can see that they are declared in the module like so:

public class PaceMakerModule extends AbstractAndroidModule
{
   @Override
   protected void configure()
   {
	bind(ISystemClock.class).to(SystemClockWrapper.class);
	bind(IRunSerializer.class).to(GPXRunSerializer.class);
    }

}

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.
Advertisements

Responses

  1. Have you ever thought about a presenter first approach with this?

  2. Thanks for the post. I appreciate seeing how others are doing it.

    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.

    Like I said, the end result is essentially the same.

    • 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.

      • You are correct – my injection technique is exactly opposite of yours.

        My presenters are in a different assembly from my activities, so each activity gets its own interface.

        My base presenter is pretty simple right now. Essentially:

        public class BasePresenter {
        private T activity;

        protected I getActivity() { return activity; }

        public void InitializeWith(T activity) { this.activity = activity; }
        }

        I’d like to find a simpler way to wire up the calls automatically, but so far, I haven’t found a way to do it.

  3. 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!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: