jetc.dev Newsletter Issue #78
Published: 2021-08-17
In this week’s issue, we look at limitations on how we can construct design
systems in Compose UI. We also look at the history of the Button()
API,
how Square adapted Workflow to Compose, and how we might add a drop shadow
to Text()
. I point out some issues with debug
builds and Compose performance.
Plus, we see how a Google engineer uses Compose Material to build a shrine.
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Creating Dashed Lines
Sometimes, we need a dashed or dotted line in a UI. There are multiple possible
solutions to this problem, and this week’s highlighted Stack Overflow question
explores two: drawing a dashed line on a Canvas()
and creating a custom Shape()
to apply to the background of something like a Box()
.
Principle of Least… Modifiability?
We are encouraged to create custom design systems as part of our work with Compose UI,
wrapping existing composables in ones that implement our design requirements. However,
you still wind up needing to offer flexibility with those composables, owing to how
Compose is set up, as we see in this week’s highlighted Kotlinlang #compose
Slack
thread.
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Medium: Pushing the Right Buttons in Jetpack Compose
Louis Pullen-Freilich, Matvei Malkov, and Preethi Srinivas of Google’s Compose UI
team give us a tour of the history of the Button()
composable. Its API changed
a fair bit in its two-year history, and the team explains why they made those API
changes, ranging from developer feedback to improving discoverability to dealing with
underlying Compose changes.
Video: Building Shrine in Compose
Chris Sinco on Google’s Android tools team walks us through the use of Compose UI, building an implementation of the Shrine Material Design “study” and showing how Material Design gets expressed through composables.
Jetpack Compose Support in Workflow
Square created a library called Workflow that represents their foundation for constructing UIs in Android and iOS. Zach Klippenstein recounts Square’s approaches towards adopting Compose support in Workflow, as an in-depth analysis of how to take an opinionated architecture framework and adapt it to a similarly-opinionated UI framework.
Jetpack Compose - Text Shadows
Sam Edwards is back, looking at how to add a drop shadow effect to Text()
.
This is a stock option for <TextView>
and is somewhat less straightforward
to do in Compose UI. Sam illustrates a few approaches, one of which hopefully fits
your needs.
Video: Migrating to Compose
Rivu Chakraborty delivered a droidcon Online presentation, looking at the work involved in migrating an existing app to Compose UI. This includes what changes you should make to your code before starting that migration, to make it easier to adopt Compose incrementally.
Medium: Recreating Google Podcasts’ Speed Selector in Jetpack Compose
Google Podcasts allows you to adjust the playback speed of the podcast that you
are listening to, using a widget reminiscent of a SeekBar
, but with custom
styling and behavior. In this post, Francesc Vilarino Guell shows how to create
a composable with the same basic look and feel, including handling the gestures,
managing the animations, and snapping to specific values.
Medium: Accompanist — The First Chord
Google’s Accompanist family of libraries contain a wide range of composables and related code. Oleg Zhilo gives us a quick tour of what is all in those libraries and what their roles are.
Jetpack Compose Side-Effects — LaunchedEffect
Udit Verma has started a series of post looking at the ...Effect
series of composables.
The overall vision is that composables should be free from side effects, which means
if you do need side-effects, you need to handle them with care. LaunchedEffect()
lets you run coroutines with a scope tied to the current composable, and Udit shows
how you can use it.
Other Interesting Links
- How to make Jetpack Compose navigation easier and testable
- Medium: List view with Pagination using Jetpack Compose
- How to animate BottomSheet content using Jetpack Compose
- Detect Instagram-like gestures with Jetpack Compose
- Video: Gradient Button
- Medium: Progress Button using JetPack Compose : SSJetPackComposeProgressButton
- Medium: Handling State in Jetpack Compose
- Adopting Jetpack Compose: Theming
- Medium: Jetpack Compose — Building a RecyclerView with StickyHeader
Resource Roundup
100% pure code!
GitHub: raipankaj / JetToast
Pankaj Rai created a small library to offer toast-style popups as composables, with several customization options (colors, background shapes, icons, animations, etc.).
GitHub: michaelgrigoryan25 / cobadge
Michael Grigoryan offers a similar composable library for badges (a.k.a., chips, tags), with support for varying shapes, colors, fonts, etc.
Other Interesting Links
- GitHub: david-varela / bottomNavScaffold
- GitHub: humawork / compose-charts
- GitHub: farhanroy / ComposeCountryCodePicker
…And One More Thing
Compose is set of libraries. On the whole, this is a good thing, as this newsletter has covered in the past. Basically, we as developers get to control when we move to new versions of the library, and device manufacturers have less impact on the UI of our apps.
However, having the entire UI framework come from libraries has a cost: initial app performance.
Java/Kotlin source code get compiled to Dalvik bytecodes, which go in the DEX files of our apps. Eventually, the OS does work based on those bytecodes, in one of three ways:
-
Interpreted
-
Just-in-time (JIT) compiled, where the bytecodes are converted into CPU-specific instructions and cached in RAM for later reuse by this one process
-
Ahead-of-time (AOT) compiled, where the bytecodes are converted into CPU-specific instructions and are saved on disk for later reuse by future processes
In effect, framework classes, like TextView
and ImageView
, are AOT-compiled.
Eventually, the DEX files in your apps will also have key portions be AOT-compiled.
However, that does not happen immediately — Android needs your app to run for
a while before it knows what is worth saving. In the beginning, your DEX files will
be interpreted or JIT-compiled, and that will slow down execution.
As a result, a Compose UI app may run slower than will an equivalent app using
the classic View
system, at least until the AOT compilation process catches up.
Also, Compose relies a lot on R8 optimizations, and normally those are not run
on debug
builds, as R8 slows the build process. So, developers and others who
rapidly churn through debug app builds will have even worse performance:
-
AOT compilation results get thrown out when the app gets replaced by a new build
-
If you are using
debug
builds, R8 optimizations are not performed
Developers may need to educate the QA team, product managers, and others about
this and suggest that performance should be gauged based on release
builds that
have been installed for a while.
For more, see this Kotlinlang #compose
Slack thread
that depicts the difference between different app compilation states and their
impacts.
Or, you can subscribe to the Atom feed or follow Mark Murphy in the Fediverse.
Recent Issues:
- 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?!?
- 2024-11-19: Compose alphas! Compose Multiplatform patch! PaddingValues! Graphics layers! Swiping! Heatmaps! Navigation! And... why did we get a new production Compose BOM?!?