One Off the Slack

These articles summarize the discussion on a particular thread in the #compose channel of JetBrains’ Slack workspace for Kotlin developers. If you would like to read the original thread, you will need access to that workspace — sign up at https://slack.kotlinlang.org!

CoroutineScopes and Compositions

Florian Schuster asked:

Hey, I need a CoroutineScope that lives as long as the current composition.

Google’s Adam Powell pointed out an upcoming launchInCompose() option, for this, though it is still incubating. The key is the onCommit event of a composition, because as Adam notes:

Composition is transactional; it can happen speculatively and it can fail. By performing side effects only in onCommit-like constructs you can avoid having to detect these situations and attempt to roll back.

Today there aren’t many situations where this happens, but we’re in the process of setting things up so that composition can occur off the main thread. We’ll be able to allow large recompositions that spend a lot of time in app code to span multiple frames, while the existing app UI can still continue animating by whatever mechanism, etc.

This will also allow all sorts of background prefetching of content in recyclerview-like scenarios

(and pre-fetching seems seriously cool)

The thread then dives into a discussion between Adam Powell and Arrow’s Raul Raja about the similarities and differences between suspend functions and @Composable functions, in terms of how they wind up being implemented by Kotlin (and, in the case of @Composable, by the Compose compiler plugin).

Adam and Florian then continued to review Florian’s scenario, for which launchInCompose() did not appear to be a solution. This is in support of Florian’s control library, an MVI-style unidirectional data flow engine, powered by coroutines, that Florian is attempting to adapt to Compose.

Posted 2020-05-24, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1590086405023000


Exceptions and Compose

Bradley Campbell asked:

What’s the plan regarding try/catch with compose?

The answer seems to be… we’re working on it. 😃

Specifically, Google’s Adam Powell replied with:

we’ve had some discussions around how some error recovery constructs might work at various layers; often if something goes wrong you may want to present some alternate UI at some different layer until the condition that triggered the error passes. You don’t generally want to re-run the thing that went wrong by default whenever the recomposition would normally want to.

After all, as he points out later, you can get into some nasty infinite loops, where recomposition triggers an exception, which triggers recomposition, which triggers an exception, which triggers recomposition, …

Timo Drick also had an entry in thread with a loadingStateFor() composable that offers a loading/content/error rendering mechanism for some work being done in a coroutine.

Posted 2020-05-17, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1589678610453600


A Matter of Units

A question came up that often appears in the course of ordinary Android development, outside of Compose:

why compose uses sp, dp, instead of raw number just like flutter…

The problem is that we have varying screen densities, so we want to use density-independent units wherever possible (dp, sp). Or, as Brian Gardner put it:

I think it’s forcing the use of good patterns. Sizes should be declared in dp units so the sizes are the same on different screen densities. Text needs to be declared in sp units so it also resizes based on density but also takes into account the user’s text accessibility settings. Using a regular number would not support either of these cases

(here, “regular number” presumably refers to just using an integer value like 8 instead of one with the unit applied, like 8.dp)

The Compose syntax of using .dp and .sp extension properties, while being somewhat of a hack from a pure Kotlin syntax standpoint, are very sweet in terms of cognitive overhead. The Dp and Sp classes that we wind up using are Kotlin inline classes, so they add little performance overhead as well.

As Colton Idle points out, Android itself is very inconsistent on what units of measure get used:

As long as I can set things everywhere in dp. Maybe it’s just me, but definitely in the current android toolkit I would do setSomething(sizeInPx) and I had to do the px to dp conversion myself. Which is fine… but it ended up being a util I had to add into every project, when it should have in fact just been handled by the api in my opinion.

Leland Richardson elaborated on that, pointing out that why developer facing APIs should be using Dp and Sp in general, a lot of the Compose internals need to use pixels. And, in some cases, Compose may still be leaking pixels into APIs:

for instance, some gesture events give you pixels which might be annoying if you’re using that value in user-land where dp is the thing you want

But, overall, being intentional about units for dimensions is a vast improvement over what we do in traditional Android development. I’ll echo Romain Guy’s comment: “this is one of my favorite features”.

Posted 2020-05-10, based on https://kotlinlang.slack.com/archives/CJLTWPH7S/p1588657831209500


More!

Older “One Off the Slack” articles can be found in the archives.