It’s 2017 and 9 years after android emerged, Google on it’s yearly I/O conference finally left the status quo and became somewhat less liberal in terms of recommended apps architecture. For years folks at the Android Team didn’t really join any architecture-related discussions, as they only cared that developers properly use Android SDK entry points, aka Components (Activity, Service etc.).
Unfortunately, new developers often didn’t know anything about it, and the lack of official guidelines made them turn their apps into huge Activities with thousands lines of code. Then, a few years ago, the android developer community acknowledged that our apps turned into a mess and began re-discovering common industry solutions for cleaner GUI code. Multitude of different solutions emerged, all of them trying to figure out the best way solve both android-specific and more common problems like:
handling UI component lifecycle,
persistence of data across configuration changes,
avoiding clutter and keep classes simple and testable,
handling asynchronous operations in clean matter.
So what new tools did Google provide us with to better handle these cases?
LifecycleObserver - custom libraries can now attach to Activity/Fragment’s lifecycle, so that the user doesn’t have to forward lifecycle events like onStart/onStop.
LifecycleObserver can also (finally) check in which state the activity currenty is, based on these events.
LiveData - an observable data holder that is aware of Activity/Fragment’s lifecycle, so that you don’t need to think about it. Comes with 2 transformations: map and switchMap.
ViewModel - a component that is persisted during configuration changes.
At netguru, we always strive for better code. Our Android team, currently uses MVP architectural pattern along with rxJava for asynchronous operations and Dagger as their dependency manager. When Google came up with the new architecture components, we were naturally curious whether they can help us build better apps. So I created a sample app. Two apps, to be exact, both doing the same thing but in different architectures - MVP (with rxJava) and MVVM (with the new ViewModel, LiveData and not-so-old DataBinding).
In this app you can type your city name and receive result from the Teleport public API that informs you about this city’s description and scores, ranging from 1 to 10, in areas like housing, safety, commute, environmental quality or tolerance.
This app showcases:
fetching data from API using Retrofit,
handling configuration changes in both MVP and MVVM,
injecting ViewModel with Dagger,
usage of DataBinding.
So what did I learn during this process?
It turns out that both architectures do a pretty good job in terms of writing more maintainable code. New components backed by Google will allow new developers to embrace good architecture earlier in their career, so the quality of all apps in the Android ecosystem should get a little better.
That being said, I still find MVP to be a more clean solution - while MVVM’s way of subscribing to ViewModel and declarative UI binding are both interesting, they come at a price. Binding data to views without touching java code is nice, but when a project grows, the code will be split between java and xmls, which may create a mess (of course business logic shouldn’t be contained there).
I also see a little additional value in ViewModel component - it helps in save-restore management on configuration changes, but it’s something most developers have achieved long time ago with custom solutions.
As for LiveData, it looks a bit like a Google’s in-house solution replacing rxJava, but only at the simplest level - the absence of rx’s operators makes it look merely like a shell of it, and it’s exactly what it is - simple holder for a value, not a stream.
Should you then jump on the wagon and refactor your app to MVVM? It depends for your use case, and it’s something that Google also mentions - use whatever solution works for you best.