What are the Remedies for Hives and Eczema on the Lips?

Eczema is a form of dermatitis (inflammation of the skin) that is characterized by rough, scaly, flaky, dry skin with a red appearance. Eczema on the lips (eczematous cheilitis) is referred to simply…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Promises in Android and Java

Async Workflows with Kotlin Pt II

This post is part of a series in which I set out how to implement common async-handling patterns in Android and Java using Kotlin Coroutines. If you haven’t seen them, or just aren’t as up to date as you’d like, have a squiz:

is a continuation of my previous post of achieving async/await in Android. In that, I write about how to write synchronous-looking code to perform asynchronous tasks, using Kotlin Coroutines.

Now, let’s talk about how to extend that in order to make a Promise-like syntax for managing asynchronous workflows. Why would you want to write with Promises when you’ve already got async/await? Because Promises describe asynchronous work beautifully, and sometimes that’s key to the readability of your workflow.

So, here’s the flight plan:

I gave vanilla Promises a fair crack, and it’s really bloody hard.

You can create a class with an initialiser block which represents its promised data, that also takes a function block (TIn) -> TOut as it’s then argument. Through overly complex handling of generics and thread management, that class can execute its initialiser in some thread worker and get notified when it completes, hence calling its then handler. There’s a few gross things that happen

I ended up with something obtuse, and messy, that still didn’t really work, and certainly wasn’t easy to test.

I was displeased.

I identified two problems (Or in technical terms, Gross Things) with non-Coroutine Promises. Writing them with synchronous then-chaining, and signalling the Promise when it is able to be resolved, was one. The other was operating on the UI thread without blocking.

You may recall from part 1 that coroutines can run async code on the UI thread non-blockingly, really easily. You may also recall that we went on to very simply start coroutines on a worker pool that do the async work, while a lighter coroutine on the UI thread chills out and awaits them, then renders the results to the UI. All without blocking. That solves problem 2.

How about Problem 1? Well, it happens that Coroutines have Deferred<T> as an intuitive starting point already defined. Deferred<T> represents a deferred result of some asynchronous task ,that is both await-able out-of-the-box and get signalled when its work is complete, which is precisely what a Promise needs. It just has a different name and doesn’t have chaining operators. Yet.

Handily, Kotlin supports two key things: type aliases, and extension methods.

Simply use a typealias so that we’re working with Promise instead of Deferred. Entirely optional but heck, when life gives you lemons, make Promises

Start by extending the Promise class with then and thenAsync method signatures, to allow Promise-like chaining.

Whatever handler is given to then needs to be able to run UI-bound tasks. So by requirement, it needs to run a coroutine bound for the UI pool. Easy.

Every Promise needs to execute its provided then handler after it resolves. Instead of using complex signalling to notify it of completion, we can just await it with await.

The thenAsync needs to additionally await the handler’s output, in order to flatten the returned object. This is as simple as just awaiting both workloads.

So now we can work with Promises, we just need to have an instance of one to work with. As it’s just a typealiased Deferred<T>, following regular coroutine async/await, we can use an async { ... } block in order to get a Deferred<T>. That somewhat breaks the semantics of our goal, so instead make a Promise pseudo-constructor!

Now we’re pretty much all done, it’s time to use what we’ve created. We’ve made some syntactic sugaring to wrap a piece of work in a non-UI-bound coroutine that returns a Deferrable as a Promise, and an interface that allows us to create a new coroutine on the UI thread for each piece of chained work done by a then block.

So we start by wrapping a unit of async work into a Promise

and then chain calls to the Promise

or execute further asynchronous work

Introducing a catch block is certainly possible, but in strongly typed languages, it’s messy. The problem is that fundamentally, .catch { ... } needs to return a concretely typed result, like a Promise<T>. But the body of the catch block will only execute if there was an error to catch, or else it will return a Promise of its input without change, so the function signature is something like

But Java and Kotlin can’t return a mixed type T1 | T2. Instead it could return a Pair<T1?, T2?> with each possible result represented by the first and second properties of the pair, but then successive then calls needs to check the contents of the pair to know what it’s operating on, and successive catches start making Pair<Pair<Pair<..., T2>, T3>, T4>. Messy.

Instead, because we’re using Coroutines which execute synchronously, we can just wrap the whole chain inside a try/catch. E.g.

Again, we can’t have multiple catch blocks at different stages of execution, but I feel that to add that would cause more stress and messiness than it would solve. Most often, I only have a singlecatch block anyway, so this suits my needs.

And there you go! Promises in Android (and Java). Who ever thought we’d see the day? I haven’t battle-tested these in productionised apps just yet, so if you have any feedback, hit me up in the comments!

Add a comment

Related posts:

Handling newlines with React

Suppose you have a Javascript variable containing multiple lines of text that you want to render in your React component. More or less you would have the following code: If you try to run this…

Carrying A Purse Makes You A Target

I love to travel. I often read articles with travel tips about how to pack, what to pack, and what to carry. I need to contradict one often suggested tip. Do not carry a well-made purse with a good…

Charges Dropped Against Jussie Smollett

Despite the fact police investigators have plenty of evidence to convict Smollett, prosecutors decided to drop all of the charges against him. Ironically, Chicago’s mayor, police superintendent, and…