On the web there is a big debate about the best architecture for native Android Apps, and there are lot of articles where MVC is compared to MVP and MVVM.
Why there are so many articles about the architecture for Android ? The answer is quite simple if you have ever written a small App that started to grow due to the customers requests, but where every new implementation makes the lifecycle of the single elements more complex to be managed. Have you ever reached that point where the addition of a simple function, that might have required 30 minutes, became a job of a day because a small change requires you to modify lot of files and the errors start raising at each breath ?
This is a very common scenario for professional developers, and this is the right moment to stop coding and start thinking how to avoid these problems that are very painful. There are lot of things we can do as programmers to solve this problem, and these are the possible answers:
- Move all the business logic out of the Activity/Fragment and put it in one or more classes
- Create these logic classes only once in the App, better without using the Singleton pattern (to simplify the testing process: do you write unit tests, right ?)
- Create a consistent interface for the callbacks invoked by these classes for asynchronous methods
- Separate as much as you can the UI logic from the business logic and don’t let the business logic know anything about the UI logic
- Unit test all the business logic and with code coverage check that all the possible paths are tested
Of course, the later you refactor your code, it became more painful and time consuming.
For this reason I always suggest you to always create, even for the simplest app thay might require you to build, an infrastructure that give you the opportunity to grow it indefinitely without worry anymore about the type of problems you might encounter in the future.
Besides, this process takes more time the first time, but for every new App the initial steps are implemented easier and quicker, and as a side effect you will always have a clean and consistent structure between all your projects.
Since my first Android App I adopted the MVP architectures, and it worked well for many years. The only problem I had with this pattern was the high number of files created to support each activity, and the fact that I used the singleton pattern for the classes where I put all the runtime data of the App. This became problematic for testing, and the level of testing for the Android App was much lower that I’m currently used for Java and JavaScript. So, for a new big project I was involved in three months ago I needed to do something to improve the architecture where the requirements were:
- Unit Testing everything (except the UI)
- Remove the singleton pattern and use IoC (I have used IoC for ten year or more on the Java backend system and it was the best decision I have ever taken)
- Simplify the access to the components (views) defined in the xml layout files to reduce the amount of code inside each activity
- Remove the dependency with a custom library I created many years ago based on HttpsUrlConnection to a more standard library
So, one month before writing a single line of code, I started a search on the web to read about the experience from other programmers and about some possible solutions to my requests. Almost immediately a solution emerged that it was the following:
- MVVM architecture (Model – View – ViewModel) to define the flow of the information: View knows and talks only to the ViewModel, ViewModel knows and talks only to the Model, Model notifies information to everybody is interested in but without knowing anything about the ViewModels that might be listening, ViewModel notifies information to everybody is interested in but without knowing anything about the View that might be listening
- Dagger 2 for IoC: all the service classes to communicate with a Restful Service or to maintain the status of the App are created at startup and are always available to everybody that needs to use them; besides i can write unit tests mocking them quite easily
- DataBinding for user interface: no more findViewById or @BindView
- Retrofit for communication: all REST API in one interface
- RxJava for asynchronous events: weak links between classes
Every single piece would have allowed me to satisfied my needs, but I had a problem: I wasn’t able to find a single article from anybody that showed me how to put all these pieces together.
So I did everything by myself, and this might be next post where for the first time I might publish a tutorial.
In the meanwhile I strongly suggest you to read about the above subjects: MVVM, Dagger 2, DataBinding, Retrofit and RxJava, because I will not enter in the details of the problem they solve but I will use them.