Beyond the Basics: Dependency Injection and the Model-View-Presenter pattern (part 1)
I’ve been developing for Android on and off for just over a year now.
I found it reasonably straightforward to make a start and built some fairly complex apps quite quickly. I wrote a couple of posts about how I did it.
Diving in and just starting to do stuff is great because it’s fun to get your hands dirty, and the sense of achievement when you build your first ’activity with a tabbed viewpager containing fragments with list views that have headers and footers’ is very rewarding.
However, now I have a couple of apps that need maintaining this carefree style of just-make-it work becomes a burden. It’s time to figure out some better ways to do this stuff.
The first item on the agenda was some kind of dependency injection. It’s easy to get caught up in dependency hell, where activities are creating instances of classes, which in turn create instances of classes which create adapters which update views which eventually have to figure out how to handle user interactions. Nothing is testable or easily swappable and everything is tied together with sticky string. Stuff will work, but it’s not going to be much fun to build upon in future.
I’ve heard good things about Dagger for dealing with this problem. After fiddling around a bit with Dagger 1 briefly, I took a look at Dagger 2 and the API immediately made a lot of sense to me. Using the port of U2020-mvp to Dagger 2 I was quickly able to pull together an example app and immediately begin to see the benefits of injection.
The Component/Module setup makes swapping out dependencies for debug, release and test variants very straightforward. There is a lot of setup code, so this might be overkill for simple apps, but the solid foundation this setup provides is almost certainly worth the effort for all but the smallest of projects.
While an identical approach doesn’t quite make sense on Android the MVP pattern targets similar outcomes.
The idea of both approaches is for each layer to be independent of the others, and for communication to happen over clearly defined interfaces. This manifests in a data model, a presenter, and a view. The presenter here fulfils a somewhat similar role to the controller in an MVC setup, requesting data from the data layer, formatting and figuring out how to supply it to the view. However, where a Controller in MVC is usually the entry point which decides which view is displayed, with MVP on Android the View is often the current Activity or Fragment. This means the view takes on some of the responsibility for kicking off requests for data, and then implements interfaces that the presenter can call to update the view.
These two patterns provide what appears to be a very flexible system for the basis of an application. Clear code separation and the modular dependency injection approach allow for testable, loosely coupled code, which can be easily swapped out, refactored, and tested without the overheads of navigating a maze of spaghetti.
I’m really only scratching the surface with this post, but I’ll share more in future as I work on building out my base application that I plan to use as a foundation for future projects.
Testing and incorporating more complex views in to the MVP architecture are next on the agenda.
Take a look at the sample app on Github, and let me know what you’d do differently. I’m happy to hear any constructive criticism or discussions surrounding these techniques.