jetc.dev Newsletter Issue #134
Published: 2022-09-27
We got a new beta for Compose 1.3.0, and stuff keeps changing!
In addition, we look at animations and dual-pane UIs, plus steppers and lock patterns. However, a growing concern is performance, so we look at upcoming Flamingo composition tracing, and I worry about how weird our composables are going to get as we deal with this and other limitations.
Ooooo… What Did We Get?
Reviewing the release notes for the latest Jetpack Compose update!
Compose is out with a 1.3.0-beta03
release!
The big thing is that the lambdas that you pass to remember()
and rememberCoroutineScope()
are now considered to be crossinline
. You cannot perform an early return from
a crossinline
lambda expression. That was never supported anyway, apparently,
but now you get a clearer compiler error.
In addition, we got more stuff that seems like it should not be in a beta, such as:
-
Line-breaking options for
Text()
-
A new
withConsumedWindowInsets()
modifier -
An experimental
pullRefresh()
modifier for the popular pull-to-refresh pattern
(these are all great, but they feel more like changes that belong in an alpha, not a beta)
Wear Compose has a new 1.1.0-alpha06
release. In addition to fixing a PositionIndicator
bug, they added a scrollAway()
modifier for Column()
, LazyColumn()
, and
ScalingLazyColumn()
. The primary use case is to allow you to have the TimeText
scroll with the content.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
How Do We Control Text Overflow?
It’s a common requirement: you need something to immediately follow some text,
remain close to the text (i.e., no extra whitespace), but also force the text
to wrap or ellipsize to control maximum width. Learn about the fill
parameter
to the weight()
modifier, and how it can help with this case, in this week’s
highlighted Stack Overflow question.
How Do We Linkify Our Text()?
TextView
has android:autoLink
, backed by Linkify
. This was handy but prone
to problems. There is no direct analogue for Text()
in Compose UI, but learn
how to set it up yourself (and problems in doing so), in this week’s highlighted
Kotlinlang #compose
Slack thread.
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Medium: Jetpack Compose Composition Tracing
Google’s Ben Trengrove walks us through some new performance analysis options in the upcoming Flamingo version of Android Studio. Compose Composition Tracing marries the composable call stack with system traces, to help you identify what composables are contributing to hot spots in your app execution.
Medium: Composable Functions
Google’s Chris Arriola continues a series of posts on Compose basics, this time looking at what it means for a function to be “composable”, what “recomposition” means, and assumptions that you should avoid when creating your composables.
Video: Taking Jetpack Compose animations to the next level
Katie Barnett delivered a presentation for GDG Melbourne focusing on animations. There is a dizzying array of animation options for Compose; Katie looks at several options for animating cards (e.g., flipping cards from front to back).
Jetpack Compose Accompanist TwoPane
Kristen Halper returns, this time looking at the Accompanist TwoPane()
composable,
as a counterpart to Microsoft’s own take on that UI. While both are aware of foldables
and can help you better work with that form factor, TwoPane()
always shows both
panes, whereas the Microsoft TwoPaneLayout()
shows one or two panes based on
device posture and other considerations.
Medium: Jetpack Compose Navigation Animation
Manshi Shah continues an exploration of Compose animation APIs started in this earlier Medium post. Here in Part 2, Manshi examines animated transitions with Navigation for Compose, using Accompanist for those navigation animations.
Compose UI for iOS
Júlia Jakubcová and Tadeas Kriz experimented with using Compose to drive an iOS set of Swift UI widgets for the droidcon 2022 app. Their takeaway: if you are looking to implement a Kotlin/Multiplatform app, Compose for iOS is worth considering.
Slides: Jetpack Compose @ Swile: last year retrospective
Romain Mouton and Benjamin Orsini delivered a presentation on what it took to migrate
the Swile app to Compose UI, from creating the design system to interoperating
with the existing View
-based app.
How to remember the scroll position of LazyColumn built with Paging 3
Ferdinand Bada was running into problems with Paging-backed columns, where navigating away from and back to a column would reset the scroll position to the top. The underlying issue appears to be a classic “fixed, but not really” one, and Ferdinand walks us through a workaround.
Other Interesting Links
- Rounded Corners
- Medium: Exploring LaunchedEffect and InfiniteTransition in Jetpack Compose
- Medium: Jetpack compose ViewModel decoupling mechanism: Wireless ViewModel
Resource Roundup
100% pure code!
GitHub: maryamrzdh / compose-stepper
maryam memarzadeh created a stepper: a UI for showing the user a series of steps,
with options for going forwards and backwards through those steps. The Stepper()
handles rendering a row of step circles, with the caller supplying the names of
the steps, optional colors, plus state information for where the user is within
the step sequence. Learn more about it in this Medium post!
GitHub: mrhwsn / ComposeLock
Long-time Android users may remember using a pattern lock for their device, where
a path among a grid of dots is used to represent the equivalent of a PIN. GitHub user
mrhwsn created a ComposeLock()
function that implements the same UI, with customizable
grid size, dot and line rendering, and more.
GitHub: mateusz800 / Expandable-Compose-Calendar
Mateusz Budnik created a CalendarView()
composable that can collapse to show a week
or expand to show a month.
…And One More Thing
Compose is starting to show some cracks in its foundation.
The idea behind Compose was supposed to be simplicity: you “simply” declare what you want the UI to be based on the present state. Compose would arrange to:
-
Detect relevant state changes
-
Call your code to re-declare what the UI should be now
-
Figure out what changed between the previous UI and the new UI and make the necessary on-screen adjustments
You would just write nearly-ordinary functions to implement the code behind that second bullet. Using reactive data sources would “just work”, and Compose would be efficient when doing all of this.
And, at a high level, that is all still true. But, we are starting to see where the simplicity is not holding up:
-
Over-composing — doing unnecessary recompositions due to state changes — is a significant problem, dragging down performance. The good news is that the tooling is getting better for this, particularly in the Electric Eel and Flamingo editions of Android Studio. The bad news is that we have to start introducing artificial workarounds, like converting parameters into lambdas to reduce composition counts, as seen here and here.
-
Part of the theory behind composables, particularly the stock widgets, is that they are stateless. That is not always possible in practice. Last week’s warnings about
TextField()
stem from state management inside ofTextField()
, necessary because it needs to interact with external-to-Compose elements, such as the soft keyboard. As a result of this hidden state, we have to take steps to ensure that our composables are not wrecking that internalTextField()
state management.
Neither of these things are show-stoppers. However, they do throw sand in the gears of Compose development. Worse, for teams who are currently considering whether or not to make the move to Compose, these sorts of problems cause more 🤔 or 🙃 than 😀.
In other words, some may feel that they are headed towards the trough of disillusionment.
If many more of these sorts of problems show up in the short term, Compose may be in for a rough go of it for a while. In the long run, it seems likely that Compose can be augmented to handle these two problems more naturally.
And, in the meantime… be sure to check your composition counts.
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?!?