jetc.dev Newsletter Issue #214
Published: 2024-05-14
The Navigation for Compose support for type safety triggered a lot of reactions, so we see what developers had to say! We also research performance, identify differences between states and flows, and play an accordion. Plus, we spend a bunch of time with Compose Multiplatform for iOS, especially Compose Cupertino, and I talk a bit about where and when I would use those technologies.
Ooooo… What Did We Get?
Reviewing the release notes for the latest Jetpack Compose update!
Compose Multiplatform is up to 1.6.10-rc01
,
with a noteworthy limitation on Android,
and otherwise with a few bug fixes. But, we’re clearly getting close to a stable
1.6.10
release!
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Why Is My derivedStateOf()
Not Reacting to Changes?
derivedStateOf()
reacts to changes in State
, not ordinary variables. This is why mixing-and-matching
the use of by
and a destructuring =
with State
can get you in trouble: by
means the variable is a delegate
and remains connected to the underlying State
, while a destructing =
leaves you with just
a plain value. See this in action in this week’s highlighted Stack Overflow question.
How Can I Remove Button Ripples?
Touch feedback for widgets like buttons is very important… except when it is not. See
some options for undoing the default Material ripple effect, and why you might want that,
in this week’s highlighted Kotlinlang #compose
Slack thread.
Nav for Compose!
The latest Navigation for Compose release (2.8.0-alpha08
) got a fair bit of attention!
Stefano Natali gives us an overview in
Medium: Compose Navigation 2.8.0.
One of the focus areas in this release was type safe navigation, and for that, opinions vary:
-
Edgar Miró is a fan: Medium: Type Safety in Navigation Compose
-
S M Mohi-Us Sunnat also likes it: Medium: Enhancing Type Safety in Navigation with Jetpack Compose
-
Boobalan Munusamy wants nullable
Int
andBoolean
type options: Medium: Assessing Type Safe Navigation Compose in Android Development
Composable Commentary
Posts, videos, and other new information related to Jetpack Compose!
Medium: Getting the native iOS look & feel in your Compose Multiplatform app
Jacob Ras explores the Compose Cupertino library, which offers themes and wrappers that give you composable wrappers around native UIKit components, in addition to an adaptive set of themes and widgets that offer Material Design on Android and a mix of native and emulated iOS widgets for Apple’s devices.
Mastering Jetpack Compose Performance: Part 2
Sagar Khurana “delves into the Compose Compiler Metrics Plugin, offering insights on immutable and mutable objects, and providing practical solutions to common performance issues”. See Part 1 of the series here!
Medium: Build Wear OS application using Jetpack Compose [Part 2— Get started with WearOS]
Aritra Das walks us through creating a Wear Compose project and using basic
composables, such as Chip()
/ToggleChip()
, Stepper()
, TitleCard()
,
and more!
Medium: My Favourite SwiftUI Component Missing from Compose
Speaking of Stepper()
, Chris Mederos missed having that in ordinary Compose,
so Chris put together some StepperButtons()
that can be used in the trailing
position of a TextField()
or OutlinedTextField()
to offer a similar UX. Chris
created another version that ties into Compose Cupertino
to even more closely match the iOS stepper look!
Medium: Reducing recomposition on Bubbles
Rogelio Robledo works on an app with a bubble chart with some expressive animations. In this post explores various steps the team took to boost performance by eliminating some recompositions, to be better able to handle lots of bubbles at once. Specifically, Rogelio looks at a few forms of deferring reads, using lambda forms of some modifiers.
Medium: MutableState or MutableStateFlow: A Perspective On What To Use In Jetpack Compose
You might think that the answer is simple: in a Compose app, for modules with
at least the Compose runtime library, use MutableState
over MutableStateFlow
.
Kerry Bisset explores this idea and concludes the opposite: all else being equal,
prefer MutableStateFlow
and other Flow
implementations.
Other Interesting Links
- Bottom Bar Navigation in Android with Compose Navigation
- Building a Custom OTP Input Field in Jetpack Compose
- Enable Edge to Edge in Android Jetpack Compose (Transparent Status Bar)
- Inserting Your (Processing) Sketch in a Jetpack Compose Screen
- Medium: Compose Multiplatform LifecycleOwner Gotchas
- Medium: Compose, Crafting with Conditional Modifiers
- Medium: Crafting a Tempo Picker in Jetpack Compose for Effortless BPM Selection
- Medium: Create a Pomodoro Timer using Jetpack Compose and MVVM
- Medium: Create compose custom layout-”Easier than you think “
- Medium: How to Create Custom Graphics with Jetpack Compose and Kotlin on Android
- Medium: Introduction to Jetpack Compose and Migrating RecylerView to Lazy List
- Medium: Jetpack Compose Best& Bad Practices with Common Usages Part II
- Medium: Jetpack Compose LazyColumn vs View System RecyclerView
- Medium: Jetpack Compose navigation simplified with Voyager for Android & Kotlin Multiplatform
- Medium: Jetpack Compose — Chapter 9: Simple Guide to Adding a TextField
- Medium: Making Your UI Pop: Explore Jetpack Compose Animations
- Medium: Mastering Compose: Custom Layout and Scoped Modifiers
- Medium: Migrating an Android app to iOS with KMP — Part III: UI and Compose Multiplatform
- Medium: Storing data in local database like a boss: Introducing Room in Compose Multiplatform
- Tidbits About Compose Web
- Unveiling AndroidFragment: Migrating Navigation from Fragments to Compose
- Video: Let’s compose this presentation!
Resource Roundup
100% pure code!
GitHub: tusharhow / Connext
Tushar Mahmud released a library that puts a convenience wrapper around connectivity
state, including a CheckConnectivityStatus()
composable and a getNetworkType()
extension function on Context
.
GitHub: sergio11 / brownie_ui_library
Sergio Sánchez Sánchez brings us Brownie, a library for Compose for Android with an MVI implementation and related components, such as a loading state.
Gist: NakaoKisho / Accordion.kt
GitHub user NakaoKisho offers us a small implementation of an Accordion()
composable, which expands and collapses to show a column of additional content.
Notable Releases
Horologist – Google’s adjunct library for Wear Compose – is
up to 0.6.11
,
mostly to get on a newer Wear Compose alpha build.
Maps for Compose has a 5.0.0
and a 5.0.1
.
These introduce breaking API changes, notably where the content
parameter
to GoogleMap()
is no longer nullable, but defaults to an empty lambda.
Jaewoong Eum’s colorpicker-compose
is up to 1.0.8
with bug fixes and updated dependencies.
Alex Styl’s compose-menu
is up to 1.3.0
,
with support for the Kotlin/JS flavor of Compose Multiplatform.
…And One More Thing
In the Fediverse, Juhani Lehtimäki wrote:
I’m fully sold on KMP but not on Compose UI. It has the same problems as Flutter and other cross platform UI, it doesn’t feel fully native on iOS, ever. You’re already in the uncanny valley and /or chasing the latest UI stuff on iOS as Apple doesn’t allow the teams to prep for new OS releases.
I understand his point. My counterpoint: not all apps are created equal.
Would I use Compose Multiplatform, even with Compose Cupertino, adaptive layer for a first-class mobile app for iOS? Probably not. There, native fidelity is going to be fairly important, and store ratings will be crucial. I would still strongly consider Kotlin Multiplatform, but with a fully-native iOS UI. That might still use Compose Cupertino for its UIKit wrappers, perhaps powered by Redwood.
There are just very few first-class apps. After all, there are only 100 apps in the Top 100. Even if we expand this to include major brands, there are still only so many of these apps.
By contrast… would I use Compose Multiplatform for an internal-use app for a company or other organization? Yes. Would I use it for a casual app, not targeting a large audience? Yes. Would I use it for a proof of concept? Yes. Would I use it for a public app, but where the app is ancillary and not the whole of the user experience? Yes. Would I use it for a first-generation app, with an eye towards migrating to a native iOS UI later if the first generation succeeds? Yes.
Those sorts of scenarios dwarf major-brand and other first-class apps. If you are doing mobile development, it is rather likely that you are building something for which absolute native fidelity is not much of an issue. That does not mean that you have to use Compose Multiplatform, Flutter, or other cross-platform UI toolkits for those sorts of apps, but that it is a viable option.
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?!?