jetc.dev Newsletter Issue #56
Published: 2021-03-16
beta02
is out… and it’s not a big deal! Our little UI toolkit is growing
up! 🎉
So, in this week’s issue, we spend some time on performance issues, both inside and outside the IDE. We also look at Google’s Compose coding guidelines, animations, and Kotlin/Multiplatform projects using Compose UI. Plus we see what Leland Richardson’s code looks like. 👀
Beta Breakdown
Reviewing the release notes for the latest Jetpack Compose update!
beta02
was released!
So far, Google is keeping API changes to a minimum. If you had been using
SoftwareKeyboardController
, you will probably want to switch to LocalSoftwareKeyboardController
.
And if you were diving deep into Compose internals,
you may run into some hiccups with experimental APIs.
But, on the whole, migrating to beta02
should be fairly straightforward.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Scaffold() Overlap Issues
Scaffold()
is very easy to set up, but it has one usability bug: you need to
use the PaddingValues
passed to your content lambda. Otherwise, you may run
into problems with Scaffold()
elements, like a bottom nav bar, overlapping
your content. Google’s Ian Lake reminds us of this in this week’s highlighted
Stack Overflow question.
Why So Slow?
When you run your Compose app, it may appear more sluggish than you might
expect. One reason for that might be live literals, as we explore in the
“…And One More Thing” section later in this issue. But, more generally,
it takes time for modern Android runtimes to optimize your app, as we see
in this week’s highlighted Kotlinlang #compose
Slack thread.
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
API Guidelines for Jetpack Compose
Google published their documentation for how the Compose team names things,
covering such topics as WhyComposablesCapitalizeTheFirstLetter()
,
WHY_THEY_DISLIKE_UPPER_SNAKE_CASE
, and more. It also covers the expectations
around public APIs (e.g., should a composable return a value?).
Android Jetpack Compose: CompositionLocal Made Easy
Elye is back, this time with two posts. This one looks at the CompositionLocal
construct, Compose’s way of providing tree-global values without having to pass
everything through function parameters. While dangerous, CompositionLocal
has its uses.
Elye also wrote a post
looking at how to have your composables avoid window decorations using insets.
Better Handling States Between ViewModel and Composable
Igor Escodro walks us through some problems we may encounter when using hot flows with composables, and how switching to cold flows may help.
Re-gaining Orientation #1
Thomas Künneth goes where few developers seem to go nowadays: landscape mode. Thomas explores how we can detect changes between portrait and landscape and offer custom UI for each orientation.
Passing Parcelable / Serializable and Other Data in Jetpack Compose Navigation
Wajahat Karim takes a look at a sore spot with a lot of Compose developers:
passing Parcelable
objects via Navigation for Compose. The Compose team
is trying to steer developers away from custom Parcelable
objects, for good
reasons. However, some Parcelable
objects come from the framework, and we will
need to pass those through Navigation from time to time.
Building a Scroll-to-Fade TopBar
Joe Birch builds upon the parallax effect that Julien Salvi wrote about a few weeks ago, using it to implement a top app bar that fades in as an associated content pane scrolls upward.
Jetpack Compose — Pulsating Effect
Paulo Pereira wanted to animate a composable’s scale to provide a pulsing effect.
Paulo’s solution involved rememberInfiniteTransition()
to animate a Float
value to use with the scale()
modifier.
A Jetpack Compose Tutorial for Beginners – How To Understand Composables & Recomposition
Ryan Michael Kay returns with with a recap of what composables, compositions, and recomposition all mean as terms within the Compose environment.
Resource Roundup
100% pure code!
GitHub: burnoo / compose-remember-preference
Bruno Wieczorek created a library with a family of remember...()
functions that
are backed by DataStore
-based preferences, so your state is persisted automatically.
Instead of using remember { mutableStateOf(...) }
, you use functions like
rememberStringPreference()
or rememberBooleanPreference()
, with control over keys,
initial and default values, etc.
GitHub: Zhuinden / simple-stack-compose-integration
Gabor Varadi is working on Compose integration for his Simple Stack navigation engine, This post outlines how to use it, including animating changes between composables.
GitHub: mddanishansari / bootstrap-alert-compose
MD Danish Ansari has created an alert bar system reminiscent of those from the Bootstrap Web UI library, complete with dismiss actions.
GitHub: Gurupreet / FontAwesomeCompose
Gurupreet Singh has converted the Font Awesome library of icons into a Compose UI library, so you can use those icons as easily as you can use the Material Design icons that ship with Compose Material.
GitHub: russhwolf / To-Do
Russell Wolf is working on a Kotlin/Multiplatform edition of a classic to-do app,
using Swift UI on iOS and Compose UI on Android. A shared
module shares code
between the platforms, including a SQLDelight-backed data store.
GitHub: Foso / MealApp
Jens Klingenberg is also working in Kotlin/Multiplatform, with Swift UI and Compose UI interfaces. In this case, the data is loaded from https://www.themealdb.com/, using Ktor for the network I/O.
GitHub: lelandrichardson/compose-dogfooding
Google’s Leland Richardson has been livestreaming some Compose coding sessions. This repo has links to those streams plus the code that he developed during those sessions.
GitHub: timusus / lift
Tim Malseed created a small app for managing weight lifting exercises, guiding you through your requested sequence of exercise sets and reps.
…And One More Thing
For mid- to large-sized projects, I have been recommending isolating the Compose-related code into a dedicated module (or modules), independent of other modules.
My original concern was namespace pollution. There are a tremendous number of top-level functions that Compose and Compose UI introduce. Those of us with decades of programming experience remember the “good” old days where everything was in a single namespace — the resulting collisions and confusion were anything but good. Minimizing the scope of Compose’s namespace pollution, by isolating its use to dedicated modules, can help with this.
Later, I was worried about Compose’s Kotlin compiler plugin. That plugin is fairly invasive, and so the less code it needs to process, the faster your builds will be and the fewer unexpected results you might get.
Now, we also need to think about the impacts of Compose-related tooling.
In this Stack Overflow question,
a developer was seeing significant slowdowns when running Compose code in
Android Studio. Via profiling, the developer determined that the problem lies
in an isLiveLiteralsEnabled()
call that happens in lots of places in the code.
This is tied to an Android Studio feature where composable previews can be updated in real time as you edit literals in your source code. This is an interesting feature, one that tries to bridge the gap between the preview system and “hot reload”-sorts of options available in other UI frameworks. However, this adds a lot of overhead.
The long-term solution is to minimize the size and scope modules where Compose is used, so live literals are fewer in number. For projects that are already experiencing problems, though:
-
Via a status bar menu, you can disable live literal processing
-
@NoLiveLiterals
may be able to control this behavior for some scope
There is little doubt that Compose and its associated tooling is powerful today and will be more powerful tomorrow. That power has its costs, though, and that might steer you towards keeping your Compose-ified modules small and putting the rest of your code elsewhere.
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?!?