MVC on Android — an approach for testable and maintainable applications — Part I

Sérgio Serra
7 min readMar 30, 2016

Update November 2018

Please have a look at my newest library !!

In this series of articles i want to share what i learnt in past years developing Android applications and how i structure my apps to be testable, maintainable and keep my code organised.

I divided this article in three parts:

  • Part I , I’ll talk a little about the MVC pattern, Android libraries i normally use and how to structure an Android project.
  • Part II, I’ll show with code examples how i separate responsibilities within the app, dependency injection, background work, data binding and some good practices.
  • Part III, last part of this series will be about unit and integration testing for Android with Espresso, Mockito and JUnit.

This series of articles presents only a possible approach and there are many more ways you can structure Android applications. My goal is to help new developers in Android to understand how to build better applications, how to integrate the several (fantastic)libraries in Android ecosystem from background work to DI, networking, testing, database and more, something that i had some trouble when i started learning Android.

I hope that i’ll also learn from writing this articles and through the feedback and critics from other developers.

MVC( Model — View — Controller)

The MVC is a classical software pattern to achieve the separation of responsibilities within code. There are three main components in this pattern: model, view and controller.

View — The view component normally represents a piece of the UI, and should not contain any domain logic, instead is role is to listen for events like gesture or click and talk with the controller to delegate. In a web project you could see the view has the html/javascript, when a button is clicked a request is sent to the server, in an Android project the view is the activity or fragment that represents a screen in the app or a piece of it that handles the interaction of the user with the app listening for events like touch, click or gestures.

Controller — The controller works like and intermediate between the view and the model. It’s work is to receive requests from the view, parse the request and call the correct model to handle that request. Normally the controller is a simple component but some variations can get more complicated when the controller also receives the result from the model and updates the view.

In a web project you can see a controller like an object that receives the request “GET /users”, parse the request and calls a method called getUsers() that will retrieve a list of users.

In Android a controller can be an object that receives the request when a button is touched and will talk with with the model to do the heavy lifting.

Model — The model is responsible for the heavy lifting, all the core logic and behavior should be isolated in a model, this way it can be reused and tested separately. This way we avoid code duplication. In Android it can be for example an Android Service or Job from Path’s JobQueue. A model can notify the UI by it’s own or talk with the controller and the controller will update the UI. I normally use the first approach and use an event bus library to do the data binding between the model and the view.

Diagram showing how components interact with each other
  • Step 1 — the view will talk to the controller requesting an action
  • Step 2 — the controller will parse the request and choose the right model to execute the request
  • Step 3 — the model executes the request and notifies the view with the result

Why separating the logic from Activities and Fragments ?

Sometimes when starting developing Android apps, we have the habit of putting network requests, database calls or any other domain logic in the fragment or activity, however this is bad for two reasons, in my opinion, first you are going to duplicate code sooner or later, by separating the DB call or request in a separated object we can use it in any place. Second and very important to unit test code in a fragment or activity you will need to start that activity or fragment and deal with it’s lifecycle and that will make your life even harder(honestly testing in Android sometimes is a pain) when writing tests.

Activities and fragments should contain logic related to event listeners and delegate the request to the controller.

MVC on Android — Project structure

I structure the projects following the MVC terminology to help me find out what i want easily in big projects, and also using terminology i learnt when coding in NodeJs/AngularJs that separates packages by feature.

Packages structure

The above image represents the project structure that i normally use, the view package contains all the activities and fragments, each package inside the view package is named with the feature it represents, for example, “authentication”. This helps me find what i want in a rapid way.

The model package contains all the domain logic, the “api” package contains the retrofit code, the “db” contains DAO(data access objects) generated by the greenDAO library, the “jobs” package contains all the Jobs used by JobQueue and “pojos” is collection of plain java objects used by GSON library to serialize and deserialize JSON.

The controller package contains the controller used by views and responsible for talking with the model. So far i’ve used one main controller, another approach will be to use a controller by view, like the MVP uses a presenter for each view. In reality i’m not sure about the advantages and disadvantages of each approach.

Side note:

Normally in the MVP(i’ve never worked with this pattern before) if i’m not wrong the presenter talks with the view that implements an interface and that lets you decouple the UI, you can easily swap the view as long as it implements the desired interface, i guess it depends on the requirements of the project. Because the MVP need more work to implement.

The internal.di package is an important one, this is where modules and components of Dagger live, in part II of this series i’ll show with code what modules and components are and to work with them.

The events package is a collection os plain java objects that are used by EventBus library to communicate between components.

This package structure can be improved i’ll talk about it at the end of part III

MVC on Android — Library stack

When developing an Android application taking leverage of the Android ecosystem is a must to speed up the development. There are a couple of Android libraries that i normally use in almost every app. Here is set of libraries that you don’t need to use but may very handy in the future:

UI

  • Android View Animations — YoYo, a lot of animations built in, with a fluent interface. Very helpful to give dynamic to the UI and create fantastic animations in a quick way.
  • Android Support Design Library

Util

  • Timber — A very small and handy library that helps logging in Android
  • GSON — Google library to serialize and deserialize JSON to Java objects and vice-versa
  • Event Bus — GreenDroid event bus is very helpful to communicate between components. With different thread models, an event bus allows you to de-couple your objects, instead of passing instance listeners between objects.
  • Crashlytics — To debug and log exceptions to a remote server, very helpful to debug crashes that on production apps.

Networking/Image loading

  • Retrofit — A must when talking with Restful APIs
  • ION — Another networking library fully featured, normally i use this one when not talking with a Restful API
  • Picasso — One of the best libraries to load images from network, with memory and disk cache cache built-in and several utility methods.

Background Work

  • Priority Job Queue — There are a lot libraries to do background work, i always use Job Queue, mainly because it’s very easy to de-couple the logic from the Activities/Fragments, it can persist Jobs to disk, prioritize and group jobs.

Dependency Injection

  • Dagger 2 — A fast dependency injection library. A DI library injects dependencies(objects) in your code, it has compile time checks to verify dependencies and you can easily swap modules to mock behavior.
  • ButterKnife — Butterknife is like dagger but much weaker, it helps you inject Android views and save you from writing findViewById() calls among other things.

BD

  • GreenDao OrmLite

Testing

  • JUnit, unit testing
  • Mockito, library to create mocks, stubs, spies and everything you need to test apps
  • Expresso, the best out there to UI test android Apps
  • Monkey, stress tests by sending random touch events to your app

External References

Couple of (very) useful links that show how to architect an Android application.

This ends the first part of this series, in part II we will see with code examples how to integrate the different libraries, the normal flow of a request like a network or DB call, how to configure DI and some good practices that are normally used in Android.

Sérgio Serra

Mobile Developer @ GuestU for Clarice App

sergioserra99@gmail.com

http://www.clariceapp.com/

--

--

Sérgio Serra

Android Enthusiast, Mobile developer, UI/UX fan, like to great user experiences.