All the nitty gritty dirty Android stuff like sensors, notification mechanisms, screen details, database access, Internet access, etc.

IV. Enable your components to be testable.

You should unit test your app as much as possible and your architecture should allow you to do it. If you can’t unit test everything, you should at least cover your business logic with tests. Separation from the real world goes nicely with this. It’s easier to test your business logic if it is clearly separated from the rest of the app.

First iteration — God activity

public final class UsersActivity extends ListActivity { @Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//...

new ListUsers().execute();

}

private final class ListUsers extends AsyncTask {

@Override

protected Void doInBackground(Void... voids) {

// final SQLiteOpenHelper sqLiteOpenHelper = ...

// JsonObjectRequest jsObjRequest = new JsonObjectRequest

// (Request.Method.GET, url, null, new Response.Listener(){ //MySingleton.getInstance(this).addToRequestQueue(jsObjRequest); // showData(user);

return null;

}

}

}

You have probably seen code like this back in the “olden times.” If you haven’t, you’re young. What’s wrong with this? Everything!

We have an activity that touches databases, goes to the Internet, does parsing, spawns threads, and renders data. So, all the stakeholders are looking at the single class, none of the concerns is separated, it’s not testable, and business logic is mixed with the Android stuff.

Second iteration — MVP

The first approach obviously didn’t work. One of the first things we tried was MVP, or model-view-presenter. Everybody is familiar with MVP. It is one of the most popular architectural patterns. It looks something like this:

Here we have separated views that are actually our Android fragments, we have (domain) models that represent our business, and finally we have presenters that coordinate all of that. It’s better for sure. Concerns are somewhat separated, stakeholders aren’t so confused anymore, and you can write some tests. We are still mixed up with the real world, though, as the presenter directly touches the database and everything. The elephant in the room here is the presenter. It’s a god object. It deals with the models, it sends the data to the view, it holds the business logic (business logic are those gears :) ), and it goes to the database and Internet, fetches sensor data, etc. So yeah, better, but it could get way more better.

Third iteration — MVP + managers

What does government do when it doesn’t know what to do? It forms an agency. What do developers do when they don’t know what to do? They introduce some manager. You don’t have to name it “manager.” There are lots of names for these kind of classes: utils, helpers, fooBarBuzz-ator, etc. So, we introduced managers.

To be honest, this even sort of worked. Business logic is contained in the manager classes. Stakeholders know where to look at, concerns are sort of separated but they could be even more so, you can write more tests but you are still touching Android directly so you have to write Android test cases and prefill the database to test business logic and that’s slow. And yeah, managers tend to be huge beasts and very quickly become hard to maintain. You can argue that it doesn’t need to get more complicated than it is, that you can deliver code faster by using simpler architecture, but there will be more bugs with that approach, and maintainability will suffer.

Conclusion

In this first part of the series, we went through the challenges of creating an Android architecture that actually works. Good Android architecture should satisfy a multitude of stakeholders, encourage separation of concerns, emphasize business logic and leave framework details under the hood and enable all your components to be testable. In the second part of the series, we will show you how we managed that what worked for us. Until then, do you have any suggestions on how to create a proper Android workflow? What were the problems you encountered?