Newsletter Issue #104

Published: 2022-02-15

1.1.0 is finally stable! And, we got a new alpha of 1.2.0 as a bonus!

Beyond that, we look at the oddness of the resources() composable and why it sometimes works if we forget to remember(). We eliminate duplicate clicks in duplicate ways and look at use cases for Molecule. Google’s Chris Sinco gives us a Figma plugin and a menu-to-close animation. And I warn about how the ancient CPUs used by many Wear OS devices may cause problems for you as you try to use Compose UI on wrists.

Alpha Analysis

Reviewing the release notes for the latest Jetpack Compose update!

In addition to getting a stable release of 1.1.0, we also got 1.2.0-alpha03. Of note:

  • They are working on adding tracing logic to recompositions, for intended integration with Perfetto. Note, though, that you need to add ProGuard/R8 rules to remove this code from release builds.

  • They added movableContentOf(), which migrates a composition from one composable to another. The idea is to use this for transition animations.

  • notifyFocusedRect is deprecated, being replaced by BringIntoViewRequester.

  • They added more support for font families, with LocalFontFamilyResolver, createFontFamilyResolver(), AndroidFont, and more.

  • TextField() now remains above the soft keyboard when that keyboard is shown.

  • LazyVerticalGrid() supports specifying “the content type for items”.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

Why Can We Sometimes Forget to remember()?

remember() is a really good idea, yet sometimes it seems like we can use mutableStateOf() without remember() and things still work. See how that happens in this week’s highlighted Stack Overflow question.

Why is resources() So Strange?

The resources() composable, for accessing a Resources object, has a strange reference to LocalConfiguration.current. See why this is needed, and how it relates to some framework API quirks, in this week’s highlighted Kotlinlang #compose Slack thread.

Composable Commentary

Posts, videos, and other new information related to Jetpack Compose!

Jetpack Compose 1.1 is now stable!

Florina Muntenescu brings us the news about the 1.1 stable release of Compose and all that we get, including new touch sizes for Compose Material!

Video: Compose ALL the things! Foldables, wearables, TVs and more — with Clara Bayarri

The Code with the Italians team had another Googler guest appearance, this time Clara Bayarri. While we focus on Compose UI for phones, Google would like us to use it across a variety of form factors. See how this works and what the limitations are!

Medium: How to prevent multiple clicks in Android Jetpack Compose

Duplicate clicks on UI elements can sometimes be a problem, such as causing an action to be performed twice when the user really meant for it to be performed once. Alexander Shevalev reviews a few techniques for implementing modifiers to allow for single-click behavior.

Using Jetpack Compose with Square’s Molecule Library

Molecule is a library for creating flows from composables. Mohit Sarveiya used Molecule and Ktor to hit a GraphQL server and integrated the results into a Kotlin/Multiplatform client app. Includes bonus historical golf coverage! 🏌

Medium: Jetpack Compose meets Huawei ID Login

Huawei offers their Account Kit, to allow apps to have users authenticate themselves to the app using their Huawei IDs. In this post, Sertaç Ayhan explores how to use Account Kit with Compose UI, with a login screen that integrates with Account Kit.

Create Pie Chart with Jetpack compose

Nisha Jain walks us through creating a PieChart()composable using a Canvas(), complete with support for clicks on particular segments of the chart. See also a related post on implementing a line chart.

Medium: Learn Jetpack Compose Crossfade Animation

Elye looks at the Crossfade() animation, including combining it with other animated effects.

Debdut Saha wanted to offer a stack of cards, with a fully-visible top card and other cards peeking out behind it, reminiscent of StackView in the classic View system. Dedhut looks at implementing this using Animatable for powering the swipe animations.

Resource Roundup

100% pure code!

GitHub: aldefy / Andromeda

Adid Lal has released an early version of Andromeda, a full design system for Compose UI, apparently building on top of Compose Material. See the associated blog post for more!

GitHub: canopas / JetCountrypicker

The Canopas team is back at it, this time with a bottom sheet showing countries and their respective flags and phone number prefixes, to let the user select a country of interest.

GitHub: c5inco / shape-composer-figma

Google’s Chris Sinco brings us a Figma plugin to convert a Figma shape (VectorNode) into a composable Shape, ready to be pasted into your project.

Gist: c5inco / MenuToClose.kt

Chris Sinco appears yet again, this time with a composable animation to swap between a three-line menu icon and a close “X” icon, where the top and bottom lines from the menu turn into the arms of the X.

…And One More Thing

Compose UI performance is an issue. It seems like developers have to think about performance more with Compose UI than with equivalent View-based solutions. Part of that is the technology, which relies very heavily on JIT/AOT for optimization. Part of that is tied to our experience, where we now need to think about things like overcomposing that we are not used to. And, some probably represents just general performance problems in a highly-complex framework.

In time, all of this will be better, through improved tools, improved techniques, and improved technology. The latter comes in the form of ever-more-powerful devices. Part of the reason why Compose UI optimization is hard is because, for many UIs, current hardware can run sub-optimal View-based code well enough that we do not have to worry about wasted CPU/GPU cycles. Even with Compose UI, poor-performing code may still be acceptable, just because we have the power in the phones.

However, on the frontiers, Compose UI performance is a bigger problem in the present day. One example is with Wear OS.

Google clearly wants us to use Compose UI on Wear OS. They have dedicated libraries and composables for Wear OS. They even set up a dedicated Kotlinlang Slack channel for Wear for Compose.

And on the Samsung Galaxy Watch4, with a modern CPU and Wear OS 3, Compose UI runs well.

Performance problems crop up with everything else.

Wear OS was largely ignored by Google for years. Worse, Wear OS was largely ignored by CPU manufacturers for years, particularly Qualcomm. Even if you limit yourself to Wear OS 2 and higher, most watches sport a Qualcomm Wear 2100 CPU, from 2016. Others are worse off, sporting Snapdragon 400 CPUs (2013) or MediaTek MT2601 CPUs (2015). GPUs also seem to be underpowered.

Compose UI is slow, the watches are slow, and the combination can be a real problem. On an app that I am working on, testing on a MediaTek MT2601-powered watch leaves me with a UI where swiping pages and scrolling content is very janky.

Our “go-to” argument for Compose UI is “the app will perform better over time after JIT kicks in”. That argument is fine if the app performs acceptably at the outset and improves all the way to fairly decent in time. That argument falls apart if the app performs poorly at the outset, as users simply will not use the app long enough for performance to improve. They will uninstall the app, leave a bad Play Store review, and so on.

In the future, as watch performance improves, things will get better. But right now, while the Galaxy Watch4 appears to be selling well, it still represents a small slice of the Wear OS market.

If you are planning on supporting Wear OS, and you are planning on doing so using Compose UI, budget time for performance tuning, and have a plan for what to do if older/slower watches simply cannot run your UI well.