There was one book, which made me understand a big problem with the Android View System. The book is called Design Patterns and is written by the infamous gang of four.
In the initial chapters, the authors take you along the development process of a graphical editor based on a view system. While following the process I became fascinated by how relevant this old book (1995) still seemed and how much I could actually apply to my coding style. There was one pattern that I found especially fitting for creating a view system, the Composite pattern. And it got me thinking that the Android view system seemed to ignore this pattern, besides this book being around for so long already. The Android code design is heavily based on inheritance with very large base classes, which is for me today one of the main reasons the code became hard to maintain in the long run. Besides the fact of course that its really really old.
Then Flutter came along and I was amazed. My first thought was that they must have read my beloved design patterns book! I started learning Flutter and the coding was as smooth as imagined. I even started to look for flutter projects and considered switching from Android. But in the end, my love for Kotlin didn’t make me rush on this move.
Model View Intent
Also, I just learned coroutines and this newish MVI pattern and I very much enjoyed this way of coding. MVI again remembered me of something I read in another one of those old books — Refactoring by Martin Fowler. Precisely the chapter duplicate observed data, which says if data is used in two layers, the upper layer should control the data and the lower layer should observe it. A very familiar example is the Jetpack Viewmodel controlling a state, which is observed by the Android view layer.
The advantage of this pattern is that there is one single source of truth and there is no syncing effort between the layers. In my opinion, this is a very important aspect to MVI, but unfortunately the Android view system is not really made for this, as the views in Android have state baked into them.
This is the second reason why I'm very very excited about Jetpack Compose. It does not only solve those issues of the Android view system but does so in a very elegant way. Just check out how the animate function works and you will see what I mean 🤯
But when I initially saw that there was a state inside the composables I was wondering, why the state is not just passed down the hierarchy and controlled by the ViewModel. Luckily there some good official explanations available.
You can think of internal state as a private variable in a class. The source of truth belongs to whoever creates and controls that state
coming from the OOP world this was quiet plausible for me. A variable should be in the class, which is using it the most (in this case exclusively), also described in Martin Fowler's book as move field refactoring. A good example of a private state of a composable would be the scroll state of a scrollable element. On the other hand, if the state is actually needed by multiple composables you should lift the state up in a higher layer, this is what they refer in the documentation to as state hoisting. There are quite some other aspects to how state is handled in composables like ambient, but that's something still left to explore and to write down in another blog post fully dedicated to state handling.
Thanks for reading and to share some more thoughts on Jetpack Compose lets connect on Twitter.