jetc.dev Newsletter Issue #63

Published: 2021-05-04

This week, we peek at InteractionSource and how not to chain composables together. We explore the impacts of Compose on dynamic feature modules and see how to offer composable-specific modifiers. New libraries are available for settings, maps, and collapsing app bars. And I warn you to make time for hallway testing as you migrate your app to Compose UI.

One Off the Stack, One Off the Slack

You’ve got questions. That’s understandable!

What Is the StateListDrawable Equivalent in Compose UI?

With things like button backgrounds, we used to use a StateListDrawable to say “use these different images based upon the state of the button”. This would allow us to have different images for the pressed button state or the disabled button state from the normal button state. In Compose UI, that tends to be handled differently, using State that we observe. For states that depend on user interaction, such as whether the composable is focused, there is InteractionSource as a source of State, as we see in this week’s highlighted Stack Overflow question.

Avoid UI That Has Side Effects on Other UI

Using things like DisposableEffect, it is possible to arrange for recomposition of one composable to mutate state, which in turn triggers recomposition for some other composable. This technically works, but it probably is not what you want, as we see in this week’s highlighted Kotlinlang #compose Slack thread.

Composable Commentary

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

Sharing Compose Components Between Android and Desktop

Gérard Paligot works through a sample Kotlin/Multiplatform project that uses both Compose and Compose for Desktop. In particular, he shows how to share composables between the platforms, including having common composables reference per-platform composables via expect and actual.

Dynamic Delivery with Jetpack Compose

Igor Escodro returns, this time looking at how Compose impacts dynamic feature module development. Technically, this is not supported yet, but Igor did not let that pesky detail stand in the way!

Podcast: Compose Academy

Joe Birch has launched a Compose-specific podcast as an adjunct to the Compose Academy Web site.

Creating a Custom Modifier Attribute on Jetpack Compose

While some modifiers are available everywhere, others are only available to child composables of some specific composable. For example, weight() is only available for children of Row() or Column(). This bit of magic is handled via extension functions and a custom type as the receiver of the lambda expression that creates those child composables, as Francesc Vilarino Guell explores in this post.

Video: Android Night - Jetpack Compose

GDG Singapore hosted a 110-minute presentation by Kurt Renzo Acosta covering the basics of using Compose UI for your Android apps.

Custom Shape with Jetpack Compose

Julien Salvi continues a tour of Compose rendering, this time with a look at creating custom Shape implementations. We supply Shape objects to modifiers like background() and border(), but there are only a few stock implementations of Shape. Here, Julien shows creating one from scratch, using Outline.Generic and a relatively complex Path().

Jetpack Compose: An Easy Way to RecyclerView (Part I)

Waseef Akhtar walks through the basic steps of setting up a Compose UI application and rendering a scrollable list using LazyColumn().

Jetpack Compose — Earthquake Effect

Most developers would prefer to avoid earthquakes. Paulo Pereira elected to create one… using some randomly-applied animations.

“Composing” the Flutter counter app with Jetpack Compose: Part 1

Annsh Singh writes a lot about Flutter, but is now playing around with Compose UI. In this post, Annsh ported the “counter” app (Flutter’s “hello, world” equivalent) to Compose UI, using rememberSaveable() for retaining the counter state.

Resource Roundup

100% pure code!

GitHub: alorma / Compose-Settings

Bernat Borrás Paronella is working on a library of composables that offer similar functionality to stock Preference elements in a PreferenceScreen, following the AOSP settings guidelines. Right now, it covers simple links, plus switches and checkboxes, each in individual boxed entries with titles and subtitles. (and TIL that AOSP has settings guidelines…)

GitHub: peterLaurence / MapCompose

Pierre Laurence offers up another library, this one for implemented tiled maps. You provide sources of tiles (e.g., from files or Web services), and MapUI() takes care of loading tiles as the user pans, flings, and zooms.

GitHub: onebone / compose-collapsing-toolbar

GitHub user onebone has a reusable composable for implementing a collapsing app bar, with configurable strategies for when the app bar reappears (or expands).

…And One More Thing

As Compose and Compose UI roll along towards a stable release, teams will start to think about beginning to use these technologies in their apps. Some of those teams will focus first on “new construction”: new apps or new screens in existing apps. Other teams will prefer to start by rewriting existing UI.

There is a hidden cost to the rewriting approach: ad-hoc “hallway” testing.

Many teams have automated UI testing, using instrumented tests, Espresso, and the like. However, many teams also wind up skipping those, as they are expensive to write, expensive to maintain, and slow to run. Those teams focus automated tests on lower levels of the app and rely on manual testing for the UI.

There is nothing strictly wrong with either of those approaches. One size does not fit all.

However, what often gets ignored is ad-hoc testing, the sorts of things that team members do on a day-in, day-out basis by using the app. If you have been doing software development for any significant length of time, you will be familiar with ad-hoc testing:

  • You do something in the app

  • Something unexpected occurs, causing reactions ranging from 🤨 and 🤔 to 🙄 or 😮 (or 😭 or 😱)

  • At some point, you take steps to investigate the unexpected behavior and perhaps make fixes

Sometimes, you literally are the one doing this testing. Sometimes, it it teammates. Sometimes, it is managers or other teams within your organization. And, alas, sometimes, it is customers or other end users.

All of that feeds back into the app and makes the app better. And much of that gets thrown out when you do a wholesale rewrite.

In the case of redoing a screen using Compose UI, improvements from ad-hoc testing that fix things deeper in the app might remain, but improvements that affect your views might be lost when you replace those views with composables.

This is not to say that should never rewrite UIs. Nor is this concern unique to Compose. However, Compose is one of the bigger externally-induced reasons for rewriting UIs, and in particular rewriting the UIs of entire apps.

Make sure that as you do these rewrites that you budget sufficient time for ad-hoc testing and that you let ad-hoc testers know about screen changes. Make sure that you have good channels for ad-hoc testers to report any oddities that they see in the Compose-ified screens. Make sure that those ad-hoc testers know how to provide good reports about those oddities: steps to reproduce the problem, screenshots/screencasts, etc. And make sure that your development process has ways to take that feedback into account and make repairs.

The advantage of first applying Compose to “new construction” is that, by definition, everybody knows that it is new. The sorts of people used to reporting weird stuff will tend to be watching out for problems with new screens, where they might not realize that a rewritten screen was rewritten.

Regardless, make sure that your “eyes and ears” across your organization — including trusted beta testers — are able to help you as you work through bugs related to a Compose migration, whether those bugs come from your migration or from Compose itself.