jetc.dev Newsletter Issue #106

Published: 2022-03-08

I’m back! 👋

This week, we peek at 1.1.1 and 1.2.0-alpha04. We look at design systems and accessibility. We explore rich text, including a native Compose rich text editor. And we spend time looking at every Compose developer’s favorite subject: state management. And I grumble about Compose magic and developer documentation again.

Release Roundup and Alpha Analysis

Reviewing the release notes for the latest Jetpack Compose update!

Back before the one-week hiatus for this newsletter, Google released Compose 1.1.1. This appears to be simply some bug fixes, as one would expect from a patch release.

We also got 1.2.0-alpha04 artifacts. Of note:

  • We now get lazy font loading as an option

  • LazyVerticalGrid() has a reverseLayout parameter

  • Compose Material now exposes TextFieldDecorationBox and OutlinedTextFieldDecorationBox, designed to be used with BasicTextField() to give us a Material-ish look while offering more flexibility in terms of the details

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

Can We Save a Composable Lambda?

It is tempting to try to shove all sorts of things into rememberSaveable(), including things that cannot be saved to disk… such as a lambda expression. See where this approach goes wrong in this week’s highlighted Stack Overflow question.

Why Are Stateful APIs Discouraged?

The official position is that an API should not expose State or MutableState, but rather a property that might be backed by State (e.g., var foo by mutableStateOf(bar)). Learn why that is the case in this week’s highlighted Kotlinlang #compose Slack thread!

Composable Commentary

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

Video: Custom Design Systems in Compose

Google’s Nick Rout delivered a presentation for GDG Cape Town, exploring the range of theme customization, from simply tweaking MaterialTheme() to creating a completely customized design system.

Video: Jetpack Compose Intro and Beyond

Maia Grotepass and Thomas KĂĽnneth collaborated on a set of presentations for the Developer User Group. Maia delivered a live coding session demonstrating the basics of Compose UI, and Thomas explored Compose 1.1 and what it provides to developers and explored Material3. The session wrapped with a panel discussion.

Compose remember vs remember mutableStateOf

It is easy to remember(), but sometimes we fail to remember the mutableStateOf()… yet things still seem to work. James Shvarts walks us through the different pieces of remember() and mutableStateOf() and explains when to use the combination and when to simply remember().

Jetpack Compose Accessibility: Getting Started

Victoria Gonda explains the importance of accessibility and walks us through a tutorial that adds accessibility features to a Compose UI app. This includes how to set up a test device with accessibility services like TalkBack enabled and how to use them for testing your work.

Building an Authentication Form using Jetpack Compose

Joe Birch is back, with the first of a two-post series on building a login/signup screen using Compose UI. This post walks through setting up models for the different aspects of the login/signup flow and assembling the screen, including professional touches like IME action button support, password toggles, and more.

Complete guide to Rich Text in Jetpack Compose

Dmytro Shuba explores how we can apply formatting to text in Compose Material, looking at styling Text() and using AnnotatedString for defining styles for individual segments of text.

Medium: How to Show Snackbars Across Multiple Screens in Jetpack Compose

A problem in classic activity/fragment development is maintaining certain UI elements across screen transitions, such as keeping a snackbar visible while the user navigates. Varsanyi Botond explores how to accomplish this in Compose UI, using a central Scaffold() shared by the various screens.

Flying Hearts Animation in Jetpack Compose: Quick and Easy Edition

Aida Issayeva returns, this time showing an implementation of Instagram’s “flying hearts” animation in Compose UI. Aida uses a Canvas() to render the heart, plus visibility and position animations for the flying effect.

Resource Roundup

100% pure code!

GitHub: pChochura / Compose-Rich-Text-Editor

Paweł Chochura created a RichTextEditor() composable, supporting character formatting (bold, italics, etc.), line alignment (left, center, right), plus text size and color.

GitHub: EhsanMsz / MszProgressIndicator

GitHub user EhsanMsz brings us a library of 28 different progress indicator composables: circles, squares, lines, triangles, and… a certain video game character.

GitHub: re-ovo / slanted-text-compose

A popular UI pattern is the diagonal banner, sometimes used as a badge on some other UI element. GitHub user re-ovo created a SlantedText() composable for implementing such an element in Compose UI.

GitHub: dokar3 / ExpandableText

Another popular UI pattern is to have a piece of text that initially shows a few lines and offers some clickable element to let the user expand to see the full text. GitHub user dokar3 put together an ExpandableText() composable for implementing this pattern.

…And One More Thing

This week’s One Off the Slack hearkens back to one of my original concerns with Jetpack Compose: sometimes, it is “too cute by half”.

In that Slack thread, Google’s Adam Powell rejects the notion that developers should worry about whether a particular API is backed by some form of State or something else that can trigger recomposition. He stated:

I do think it’s valid for public API types… to call out in their documentation if their properties are snapshot-observable, but with compose it’s more of a baseline assumption.

The Compose snapshot system, as a form of software transactional memory, is a seriously cool concept, but it contributes to the “Compose is magic” vibe. That is exacerbated by the fact that there is no documentation from Google about the Compose snapshot system, apart from very limited class documentation. For example, "snapshot invalidation" has zero hits right now in the developer documentation, yet Adam focuses on that phrase a lot in the Slack thread.

Zach Klippenstein wrote a seminal set of blog posts covering state and diving deep into the snapshot system. Google integrating something like those posts into developer.android.com would be a significant help. Without that, “snapshot invalidation” and similar terms are going to be expert-level topics at best. IOW, so long as “snapshot invalidation” remains magical, most developers are going to largely ignore it to the greatest extent possible.

Right now, we are already fairly deep into rules like “if your composable is not recomposing, you probably forgot remember { mutableStateOf() }”. While technically that is incorrect — there are other options beyond MutableState — busy coders are not going to care. They are going to reach for the tool in the toolbox that they know solves the problem, because recomposition is ancillary to the real problem that the developer is trying to solve.

My hope is that someday there will be adequate official documentation for the snapshot system, and that “snapshot invalidation” will appear in the docs.