Architecture

Concurrency

User interfaces are typically updated via a single thread. That thread is responsible for drawing any needed changes and responding to user interactions. The UI should respond immediately to interactions such as pressing a button, scrolling the screen, or drawing pictures with their finger.

Many user actions result in performing data updates, which can be expensive. If we perform these actions on the same thread that detected the user interaction, all screen updates are blocked until that update has completed. At best, this can result in "jank", an interface that doesn't immediately respond and jumps between drawn frames. At worst, an update might take long enough that the user interface freezes.

The easiest fix for this is to run data updates on a different thread so the user interface can keep responding immediately. We'll do this using Kotlin Coroutines, but it could also be done using threads and executors.

While the UI is now responsive, we can run into data synchronization, race and deadlock issues. Fortunately there are several patterns we can follow to more reliably work with concurrent processing.

One of the most effective ways to help is to use a Unidirectional Data Flow, or UDF.