Some time ago a colleague offered a cake to anyone who could assist in integrating Google's calendar and resource API. So, I do like cake and thought that I should give it a try. I started playing with the mentioned APIs and as usual, Java 8 has been chosen as a starter, which quickly led to some first results, but it would make sense to put some effort into creating a mobile application. Unfortunately, I didn't know much about Android yet, except that it's based on Java 6, resembles Swing programming and defines some custom lifecycle strategies.
If the projects source level should be kept at 1.8, that would require more attention, but the latter should be just fine.
Anyhow, there is plenty of information available on how to develop an Android application using Java 8, but it comes with the risk, that some (future) parts might not be supported or delayed by the native platform or toolchain.
However, programming in Java 6 is definitely not an option and fortunately, the internet reveals alternatives, whereas one of them is Kotlin, a programming language that compiles to Java 6. Kotlin's creators describe the language as a "Statically typed programming language for the JVM, Android and the browser (100% interoperable with Java)"
So we have a broadly known programming language on the one hand, which risk mainly emerges from the currently supported platform level, which is not 100%, and other related device limitations, like Android level, and a new programming language on the other, that provides us with a natural compatibility level, but a different syntax, concepts and some other pros and cons that can be derived.
I took a step back and decided to create a small playground for Kotlin, as it would be better for a comparison to understand how much impact syntax and concepts have if people start with zero knowledge.
A few koans later, which are also available online, and a travel through the official documentation, the decision was made for Kotlin, as it provides the highest level of compatibility and puts forward with new concepts to increase the overall code quality as well as some nice thought extension options. It doesn't take much time if people have a Java background, as many definitions have similarities, even if parts of the language keywords differ.
As a result, I started converting the project and thankfully IntelliJ provides a comfortable way to convert Java to Kotlin and to adopt the project settings for Gradle. Alternatively, there exists a "how to set up a project" in the official documentation as well as other blog posts about Android and Kotlin development.
Having laid the foundation, I began to look for common practices and general patterns with respect to mobile applications and fragments are one idea, that is listed very early in Androids documentation, right behind activities.
They currently seem to be the preferred way to handle layout modularizations, as many tutorials are based on them, but they also felt cumbersome to implement correctly as they
- define an independent lifecycle
- require some sort of external management if used programmatically
- require additional patterns if a communication with the host activity, for instance, is desired
Actually, I only wanted some sort of reusable layout management, to compose smaller items to a view, that ideally, bind their content to the correct context and values. As usual, there are many ways to accomplish this task, like
- using an annotation processor to create java language bindings for corresponding XML components
- using data binding
- using some kind of reactive components
One major difference between the variants is the degree of their code-layout separation. While the former two mostly declare their layouts in XML and define interactions by code, the latter combines both in code, or said differently,
sacrifices this separation. This may sound a bit odd initially, as we assess declarative units and code isolation better, but it eliminates consistency problems between layout and code definition, which is good if an erosion between them can't be reliably detected. It further allows us to split components into reusable units, favoring composition, that (re-)act by their values as we will see soon.
A reactive approach seems very promising, as its used by modern web development nowadays as well and the following post "THE EVOLUTION OF ANDROID ARCHITECTURE" is quite a nice and short read, which contains a cross-reference to "Advocating Against Android Fragments", addressing the issues with fragments from above. However, the article led me to Anvil, a reactive implementation for layout components written in Java that usage feels quite natural in Kotlin, but it's designed to work in both worlds. Nevertheless, a pure implementation for Kotlin is provided by Anko. The effort to switch between them shouldn't be that big, as both follow a similar DSL builder pattern.
If you went through the evolution article, then you've probably read about the term Redux, which defines an architectural pattern comparable with MVC, but with certain differences.
In short, I would say that "Redux decouples those components more strictly and enforces this distinction by the chosen architecture, patterns and conventions" and would point to the following document, which gives a short introduction and dismantling of some design pattern Redux is made of. An architectural pattern is nice, but it would be much better if we could use an implementation and this is when Jedux comes into play.
Just to sum it up: The current stack is now made of "Kotlin, Anvil (Anko alternatively) and Jedux", but if you still prefer to use Java, you can go with "Java, Anvil, and Jedux" as well.
The following article should guide you then, but I'd like to mention a few concepts that make Kotlin a good companion of Redux
- data classes are ideal candidates for action types and the state itself, as they make writing immutable and destructible code easier
- pattern matching in conjunction with smart casts makes writing reducer code easier
- named arguments and default arguments allow selective overriding of your action conventions
- delegated properties allow the writing of memoized data-bindings that look like normal properties
- extensions can provide some glue to fill gaps
- coroutines will (upcoming 1.1) give you an opportunity to handle asynchronous programming in a 'synchronous' manner, just like redux-saga
Anyhow, if you write a Redux application for Android, you should keep in mind, that Javascript uses a thread confined event loop model that keeps track of visibility constraints, whereby Android grants access to other threading capabilities next to the same confinement strategy. So its generally best to use Android's main loop for anything related to Redux, which means, that action dispatches and state renderings can be performed safely. There exists a couple of threading libraries, but the reactive extensions library looks very promising here and provides an extension for Android additionally, to reschedule any callback action back on the main loop. A simple Kotlin extension function for this library could then look like this:
fun <T> Observable<T>.eventloop () = this.observeOn (AndroidSchedulers.mainThread ())
In Redux, an application may freely dispatch an action from likewise every piece of code, which might be a service, view or a middleware component as well, iff this dispatch occurs on the correct thread, which is the only restriction Redux puts here from its background. The advanced chapter, especially the part about middlewares, explains asynchronicity in Redux quite well and mentions a couple of strategies. I would say that redux-saga, a programmable middleware based on suspendable iterators, offers the most in different categories:
- an action can still be defined as a serializable pure data type
- a saga can be further tested without any other involved Redux component, as it's defined as an iteration over simple effects
Anyhow, the concept of chainable middlewares is quite powerful and reaches from generic, e.g transport (HTTP, ..), to specific service middleware implementations, e.g domain (business code) that could act with each other in a decoupled manner. A domain middleware might dispatch an HTTP message, that gets evaluated by a different transport middleware, while the response is then put back in the store.
One last thing I'd like to mention is, that Redux is great when it comes to tests. The implementation of small building blocks allows you to focus on unit tests - without any activity and lifecycle code in mind.
Feel free to look at the application's source code or to install the APK, which has been created with Travis CI.
The photograph for this article was taken by Cam Evans.
Become a backer or share this article with your colleagues and friends. Any kind of interaction is appreciated.