In typical Android project where we need to pull data from somewhere (REST, SQL, cache, etc) into the UI in a clean way we commonly use a Loader, Service or (possibly, yuk) an AsyncTask, but I find all these approaches unsatisfactory for several reasons:
- They're ugly, especially Loaders which have an appalling API structure
- It's too easy to get wrapped up in threads, and tread on the UI thread
- Our presentation layer code is being polluted with Android code and boilerplate. We're often passing Android objects (eg Cursors) right up into to the UI layer, which makes a clean architecture almost impossible to achieve. This forces us to mix business domain specific code (ideally plain Java objects) with Android platform code - not great for readability, maintenance, testing, or flexibility for future development. In practice we often get huge, messy Activity/Fragment classes.
I'm attracted by ideas such as those outlined in these articles: http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ http://antonioleiva.com/mvp-android/ http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
Having successfully started using MVP to break the Activities/Fragments/Views into smaller/cleaner pieces, I'm now thinking that a solution to the problems above might be to rely on a message bus (Otto, EventBus, etc) instead of services or loaders or whatever to interact with the domain data.
So in practice that would mean instead of using (for example) a CursorLoader to load a Cursor from the database, I'd instead use the message bus to send a message to request data, the data is loaded on a background thread in response to that message, and then handle the response data when it arrives via a message on the UI thread. Crucially for me I'd prefer that data structure to be cast out of the business domain, not the Android domain, so I'd prefer an array of business objects, to a Cursor.
This being engineering there are always trade-offs, and although this seems to provide a much cleaner separation of concerns, there's less loader/service boilerplate, what are the downsides?
- It may be harder (especially for new developers) to understand the code
- It will be necessary to ensure the messages are sent and received on the right threads (Otto seems like it may have limitations here)
- It will be necessary to avoid the temptation to implement everything as a message, which would ultimately be counterproductive
- Passing collections of business objects around may be less efficient than using objects like Cursors. Though in many scenarios is it a problem in practice?
- I do not know if Otto/EventBus are designed only to pass very small messages, or whether it is appropriate to pass larger objects (eg an array of business objects).
My question is are there any fundamental reasons NOT to take this message-based approach with Android apps?