Recently I was lucky enough to attend Droidcon in Turin, one of the biggest mobile conferences in Italy. This year, the event was organised by Synesthesia, a key player in the Italian digital panorama, and, with over a thousand registered attendees, hosted experts from Google, Airbnb, Sky Sports, Blinkist, among others.
The venue — The conference took place at the OGR (Officine Grandi Riparazioni) in Turin, a former locomotive repair workshop, which in 2017 underwent significant refurbishment to transform it into the ultimate event space. It’s now the second year that Droidcon Italy has taken place in such a huge venue.
The talks — We were able to preview a number of talks that had recently taken place at larger scale events such as Google I/O’19, and which spanned the spectrum of software development. I appreciated the diversity of content available; there were three different tracks to follow as well as many workshops.
I tried to focus on subect matters that I believe are gathering traction, to gain more confidence in the area and to enable us to introduce these into our product offering — make sure to check out the ASOS app. The topics I chose were coroutines, modularisation of apps and animations.
I’ll take you through my key highlights on each of these topics below.
Networking the Kotlin way: Retrofit + Coroutines
Boris D’Amato walked us through a journey from traditional RxJava and Retrofit network requests architecture to a more recent and lightweight combination of the networking library and Kotlin’s coroutines.
The talk began with the basic concepts and building blocks for coroutines on Android — with Boris making a nice comparison between code in RxJava and code with Coroutines. He then highlighted the more friendly and natural feel of development with those components, and, most importantly how easy it is to debug and scan the steps within the complex operations and data transformations we usually perform for network requests.
My key take-home concept was the use of coroutineScope:
Every coroutine builder (like launch, async, etc) and every scoping function (like coroutineScope, withContext, etc) provides its own scope with a respective Job instance into the inner block of code they run. By convention, they wait for all the coroutines inside their block to complete before completing themselves, thus enforcing the discipline of structured concurrency.
The use of structured concurrency allows us to enforce boundaries, making our life easier when we need to perform simultaneous operations that we want to group as single logical units in our flow.
An interesting aspect of this is the incoming introduction of ViewModelScope , which will enable the use of structured concurrency within the widely used lifecycle component.
This particular ViewModel extension property is still in the experimental stage, but it promises to augment the power of that component by easily managing asynchronous tasks we might need to launch — basically tying the lifecycle of that work to the lifecycle of the ViewModel itself. This will eliminate all of the boilerplate code we usually have to deal with, making our development less error-prone.
ViewModelScope as part of the alpha releases is already available on the AOSP repo so the eager devs can easily integrate it into their codebase — it’s a tiny yet mighty bit of code.
Why we failed at modularising Sky Sports - An honest retrospective
As you might guess from the title, this talk by Marcos Holgado focused on looking back at the efforts his team made to transform their codebase from a monolithic piece into a more flexible one — a journey that took around a year and a half.
Marcos explained how the product at Sky is structured — a suite of complex apps built with different features and heterogeneous content including live streaming of events. This is all to be differentiated within the countries the company operates in. This has made flexibility an ever-growing necessity for the company — to be able to offer apps which are similar but different at the same time.
The vision was the fairly ambitious goal of having a set of modules so flexible and independent as to allow the developers to compose an app using a set of features of choice, for instance, news + streaming + personal account features with the ability to bundle them into a deliverable app in a very short time-frame.
The recipe for failure was an unfortunate mixture of factors: hard deadlines for releasing critical features, ensuring the company product management team were on board combined with the challenges associated with creating an effective plan.
Having flavours for gradle builds was the obvious choice to differentiate the apps by country products. They soon realised it was painful to maintain such a structure because of longer build times, frequent conflicts breaking things and ultimately the lack of scalability.
The team attempted to modularise the streaming component, a crucial and complex part of the app, but quickly ran into the ever-present dilemma — how to separate the sub-components inside. However, this was not successful due to time constraints and the sheer complexity of the task. They changed the approach and tried to start with the simplest element — Marcos’ advice is to always begin with the most valuable piece of the app first, trying as much as possible to apply KISS (Keep It Simple, Stupid) while ensuring an adequate allocation of resources when doing this kind of transformation, because…
If the team can’t understand it, you’ve already failed.
Splitting such a project was also influenced by how to structure the dependency injection, and Marcos proceeded to show what he did using Dagger, which is covered in one of his articles below.
Using Dagger in a multi-module project
Struggling to use dagger in a multi-module project? This article should help you a lot so you don’t waste the time I…
Motional intelligence: build smarter animations - Nick Butcher
Nick Butcher is devoted to animations and gave us an eye-opening talk about how they’re crucial to building apps — and aren’t just aesthetically pleasing but are also easy to use.
Animations are currently under threat as our way of architecturing apps has changed over the course of the years.
Concepts such as unidirectional data flow have many advantages but enforce a stateless implementation of how a view renders each state. On the other hand visual features such as animations are pretty much stateful, in the way they are often used between states and represent transitions between one and another. This duality is clearly a point of friction, how do we use state in a stateless context?
The answer to this is using animations that work like state machines, that can be interrupted or retargeted while running. Animations built following this concept must be:
- Reentrant — meaning that in the reactive world, a state can be published at any time, therefore the animation must be able to be interrupted and restarted at any time and react to being triggered (even when it’s already running) and react properly.
- Continuous — by using a continuous set of values when performing interpolation, to avoid jarring animations and abrupt changes in the animation properties.
- Smooth — because if we want to replicate the real world physics of motion, we must make animations so that there are no sudden changes of speed and acceleration of objects whenever there’s a change of a property in an already animated object.
A best practice for building animations requires the built-in view property animators, which provide some of the behaviours for free, e.g. auto-interrupting animations on properties when a new one is started on the view. Even better, Nick suggests using physics-based animations APIs such as SpringAnimation, which help us achieve the smoothness we’re looking for, with little effort.
We can add animations to other components, for instance, AnimatedStateListDrawable which allows us to specify a transition animation between the different states we specify, as we would normally do in a simple state list drawable. This fits particularly well in a reactive pattern — we just need to set the state to the drawable and that state will get changed via an animation.
StateListAnimators are similar to the previous ones but act on Views and have the ability to associate states with a set of animations on the properties of a View.
Nick went on to discuss the hierarchy between these fundamentals for animations; reentrant is about having a correct animation that works as intended and is fit for purpose; continuous aims to avoid jarring experiences for the user and lastly, smoothness is the icing on the cake — the final touch that makes the UI stand out.
Make sure to also check out the below presentation.
Meaningful motion design and how to implement it
Android apps are not just series of static screens. To create a great app you will have to bring it into life with…
Congratulations to Synesthesia for making such a great Android event possible, the success they’re having is well deserved. It’s always good to meet up with fellow Android lovers in such a beautiful city and venue, I’ll definitely be back.
My name is Filippo and I currently work at ASOS as an Android Engineer. I’m always on the lookout for the next Android trend and I love elegant and well-crafted apps.
Filippo Beraldo - Medium
Read writing from Filippo Beraldo on Medium. Android Engineer @ ASOS. Formerly @ EatAround and Uniwhere. Every day…
Make sure to give our app a try! We’re constantly improving it and adding new features.