jetc.dev Newsletter Issue #91
Published: 2021-11-16
This week, we look at the impacts of orientation changes on BoxWithConstraints()
,
see what Jake Wharton has been up to, and create custom themes (with or without MaterialTheme()
).
We render some treemaps and look at using blurs as image placeholders. Plus,
I wonder how tooling is going to handle composition-related memory leaks.
Also… we look at ellipsizing text.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
How Do We Ellipsize Based on Height?
Text()
supports an overflow
parameter, and a popular option for that is TextOverflow.Ellipsis
.
However, this only works with maxLines
; if you do not specify maxLines
,
you do not get an ellipsis, even if the text is truncated. While we wait
for formal support for this,
see how to implement a workaround in this week’s highlighted Stack Overflow question!
When Do Orientation Changes Take Effect?
Orientations are confusing enough in ordinary Android code. While Compose UI handles
configuration changes for us, we still need to react to the new orientation.
Sometimes that is easy, and sometimes… not so much, as we see in this week’s
Kotlinlang #compose
Slack thread.
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Videos: droidcon Berlin 2021
droidcon Berlin had a bunch of sessions on Compose UI, and their videos are now up, including:
The State of Managing State (with Compose)
Jake Wharton returns, this time with a brief look at Molecule,
a Cash App library that uses composables to drive the emissions of a StateFlow
or Flow
, instead of (or perhaps in addition to) having composables that render UI.
Video: Optimizing Render Performance of Jetpack Compose
William Shelor delivered an Android Worldwide presentation looking at why our Compose UI screens may be sluggish. Some of that is environmental (e.g., R8, JIT), and some is tied to how we write our composables (e.g., using keys properly).
Medium: Fairly Evaluating the Impact of Different Android UI Libraries on Gradle Build
Another type of performance is build performance. Chao Zhang wanted to build atop of Chris Banes’ build analysis of Tivi and to compare and contrast different UI construction approaches. TL;DR: data binding is really slow.
Medium: Application Theme in Jetpack Compose
Maryam Alhuthayfi explores creating custom versions of MaterialTheme()
,
complete with custom colors, fonts, and shapes.
Medium: How to Create a Truly Custom Theme in Jetpack Compose
Dmytro Shuba walks us through the same basic process: how to create a custom theme.
In this case, Dmytro bypasses MaterialTheme()
and looks at how you can create
a theme tied to your own app’s design system, for use with non-Material composables.
Jetpack Compose: Tabs with Swiping
Often, in Android, tabs allow for swipe gestures to switch between tab contents, instead of tapping on the tabs themselves. This is not offered “out of the box” by Compose Material. Bevan Steele explores using Accompanist to fill in this feature gap.
Integrating ZXing Android Embedded in a Compose App
Thomas Künneth is back, taking another look at something from outside of Compose UI
and determining how best to use it in a composable. Pretty much everything tied
to SurfaceView
and TextureView
will need this sort of attention, and this time
Thomas explores ZXing’s embedded QR code scanner. In this case, Thomas inflates
a layout containing a DecoratedBarcodeView
, then manages the resulting view
in a composable hierarchy.
Using SwiftUI and Compose to develop App Widgets on iOS and Android
With iOS 14, Apple started offering app widgets, which Android had for a decade prior to this. However, Google largely ignored app widgets for several years, and the original Android 1.6-era API for implementing app widgets left a lot to be desired. John O’Reilly wanted to use Kotlin/Multiplatform to drive app widgets for both iOS and Android. In this post, John explores how this went, with a quick peek at the Glance API for defining Android app widgets using composables.
Other Interesting Links
- ExpandableText in Jetpack Compose
- Jetpack Compose TextField which accepts and emits value other than String
- Navigating through multi-module Jetpack Compose applications
- Video: State in Jetpack Compose
- Add Conditional Modifier Without Sacrificing its Fluent API
- How to implement pagination in Jetpack compose?
- Medium: Handling Multiple Permissions using Jetpack Compose
- Jetpack Compose - Keyboard Types switch on focus change
- Medium: Introducing Jetpack Compose Into an Existing Project
- Medium: Easy Dark Mode With Jetpack Compose and Material Design 3
Resource Roundup
100% pure code!
GitHub: microsoft / surface-duo-compose-sdk
Microsoft is starting on a library for composables of particular relevance
to foldables, such as the Microsoft Surface Duo family. The initial composable
is TwoPaneLayout()
, for organizing two panes’ worth of content both on foldables
and on tablets.
GitHub: overpas / compose-treemap-chart
Pavel Shurmilov brings us a library that renders a treemap,
a type of chart that uses captioned areas to represent relative values in some
data set. Pavel’s implementation offers a TreemapChart()
composable, plus a
DSL for constructing a tree of nodes to use for the chart data.
GitHub: orlando-dev-code / compose-image-blurhash
Blurhash is a system for converting an image into a placeholder representation
in 20-30 characters. The idea is that a Web service could ship the blurhash value
along with an image URL in a response (e.g., JSON). The client app could render
the placeholder immediately, then swap in the full image when it is ready.
Orlando Novas Rodriguez implemented an ImageBlur()
composable that handles
rendering the blurhash placeholder, while delegating the real image loading
to Coil.
Gist: EmmanuelGuther / ComposeGradientModifier.kt
Emmanuel Gutierrez Hernandez created a small gradientBackground()
modifier that
implements a linear gradient at the specified angle using a supplied list of colors.
Other Interesting Links
- GitHub: Amrjyniat / Swipeable-Card
- GitHub: re-ovo / ZoomableComposeImage
- GitHub: floschu / control
- GitHub: LanarsInc / compose-date-text-field
…And One More Thing
Last week, I wrote about one new-to-us problem in Compose: overcomposing, where we cause a composable to recompose a lot more frequently than we expect, burning CPU cycles and causing jank.
Another new-to-us problem was pointed out by Ryan Kay and Google’s Adam Powell in a “One Off the Slack” entry from a month ago: compositions hold references to objects. So long as the composition is outstanding, anything the composition references cannot be garbage-collected.
As Adam pointed out, these things get cleaned up eventually:
If you
remember {}
something it will be hard referenced by the composition. Any lambda captures you create that Compose might need to re-run to recompose will also be hard referenced by the composition. These references are dropped when the@Composable
caller leaves the composition, or when the composition itself is disposed.
However, the underlying assumption there is that our compositions get disposed of when we think that they are. Since we do not really visualize compositions, only their results, it is possible that we would leak memory unexpectedly.
This gets exacerbated as we start using Compose for things outside of the still-new “stomping grounds”
of Compose UI. Composables used purely for data management might get held onto longer
than we expect. For example, Cash App’s Molecule
is an interesting way to have a composable drive a StateFlow
or Flow
.
Probably the composition is disposed when the associated CoroutineScope
is cancelled. However, now you have to make sure that you are using the proper
CoroutineScope
, one that will get cleaned up at the appropriate time.
These sorts of leaks are likely to be difficult to analyze with your typical sorts
of heap dumps, simply because too much of the intervening code is not ours and is not familiar to us.
We are unlikely
to recognize what a composition looks like, for example, let alone one set up
by Molecule and referenced by some CoroutineScope
. Perhaps Leak Canary
will be able to help here in time.
These sorts of problems — overcomposing, composition-based memory leaks, etc. — highlight the “two steps forward, one step back” nature of early-term Compose UI work. Compose UI significantly simplifies many aspects of Android app development, but it does create new variations on problems. Until we get the tools or techniques to help solve those problems, be prepared for “bumps in the road” as we try scaling Compose UI up for larger and more complex apps.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 2024-12-10: A Compose Multiplatform alpha! Hot reload! Presentation! Sprites! Calendars!
- 2024-12-03: Rebecca Franks on clipping and masking! Stefano Natali on graphicsLayer()! FunkyMuse on type-safe nav results! And... if we have enough maps, do we need to store our maps in a Map?!?
- 2024-11-26: Math! Shared element transitions! Custom modifiers! Macrobenchmark! Adapting to platform-specific design systems! And... why does wrapContentSize() not wrap my content size?!?