jetc.dev Newsletter Issue #57
This week, we spend a chunk of time thinking about testing, both for getting our code right now and to be able to adapt to the inevitable changes that are going to come about for how we do Compose UI development.
In addition, we explore animations and the
Canvas(), adapting our legacy Compose
code to the effect system, utility composables for design grids and zooming, and more!
Plus, we see what goes on inside Adam Powell’s head!
One Off the Stack, One Off the Slack
You’ve got questions. That’s understandable!
Espresso’s Compose UI support is powerful, but sometimes it is not obvious how to
set up certain types of tests. Simulating text entry into a
one example, and we see the solution for conducting that test in this week’s
highlighted Stack Overflow question.
Ever wonder how the Compose team remembers all of the various ways of solving
Compose UI problems? Well… you will still wonder how they remember all that stuff,
but at least you will get a better idea of the thought process, in this week’s
#compose Slack thread.
Posts, videos, and other new information related to Jetpack Compose!
Márton Braun went beyond Google’s Jetchat sample app and wrote a full-fledged chat app, complete with server support through Stream. This post walks through every step of the process, from creating the initial project in Android Studio through the final results.
Igor Escodro identifies a scenario where your Compose UI testing might wind up with flaky tests — tests that may succeed or fail based on timing issues. Igor walks through how to deal with such tests, using Barista and a slightly different structure for the test cases.
Paulo Pereira demonstrates a “curtain” animation, where a column of composables can fold out from an initial row, in a variation on the “accordion” animation. This GitHub repository contains the final result, in the form of a sample app.
Pranav Jayaraj gives us an overview of the various animate-as-state top-level
functions in Compose UI, such as
Pranav demonstrates both simple value animations and ones with a custom specification,
such as repeat rules or spring stiffness.
Julien Salvi takes a tour of the
Canvas() composable, showing how
to draw shapes, lines, and text on one, and comparing and contrasting it with the
Canvas object from the classic
View system. Julien also ties the
DSL into the animate-as-state functions from above, showing how they let you
Canvas() and affect the elements that you draw.
Andy Dyer compares and contrasts “flexbox” from CSS and Web development with the
container composables and modifiers that we work with in Compose UI. While there
is no single
Flexbox() composable, you can get a lot of flexbox-style results
from the roster of standard composables.
One challenge that we have with Compose and Compose UI is how much the API has shifted from the early developer previews to the now-current beta.
Tiger Oakes feels our pain.
Max Hübscher wanted a
TopAppBar() that would slide away as the user scrolls
the content down, then slide back into position when the user scrolls the content
TopAppBar() does not appear to offer that, so Max wrote one using a
animateFloatAsState(), and related composables.
Other Interesting Links
- Re-gaining orientation #2
- Android Jetpack Compose Navigation made Easy
- Video: How To Style And Theme Android Application With Jetpack Compose - Light & Dark Themes
- Building an Android Emoji Garden on Jetpacks! (Compose) with Realm
- Composing Web Content
- Jetpack Compose — An Introduction
100% pure code!
Olivier Patry posted a simple composable for rendering a grid of squares. That may not seem like much, but if you place it at the bottom of your screen composable, it overlays that grid on what the rest of the composable renders, for helping you visualize how well you are matching requested designs in terms of size and position of the widgets.
Daniele Baroncelli published a sample app for his D-KMP architecture, demonstrating how to use Kotlin/Multiplatform with mostly shared code, except for using platform-specific declarative UIs (Compose UI for Android, Swift UI for iOS).
Mohamed Elbehiry published Delish, a gorgeous Compose UI app for browsing and searching recipes published by Spoonacular through their Web service API.
…And One More Thing
The next year or two is going to be a period of experimentation, as we strive to find the best patterns for applying Compose UI, both for new projects and for revamping existing projects.
Just do not get too married to your solutions.
In Android app development, “change is the only constant”. The recommended app development patterns change extremely rapidly, even when the platform itself has slowed its rate of change from the wild early days. Public Android app development is barely 12 years old, yet we have gone through a variety of revolutions:
Use Java. Actually, use Kotlin.
Use activities. No, use fragments, but only for tablets. Wait, instead, use fragments for everything, with one activity. Actually, dump the fragments and use composables!
AsyncTask. No, use loaders. Hang on, switch to RxJava. Oh, can we interest you in coroutines?
Just write code. No, use MVP. Sorry, that was a typo: use MVVM. Hey, MVI looks cute!
And so on.
It is almost assured that we will go through a few generations of approaches for how to apply Compose UI. Perhaps they will not be as fundamental as some of the other Android app development changes, but they may be more numerous:
Do we stick with top-level functions everywhere, or do something else (e.g., one
How do we handle theme-like concerns, particularly if we are implementing our own design system and therefore may not be using
MaterialThemeor Compose Material?
How do we decide what gets locally
remember-ed, what gets handled by a Jetpack
ViewModel, and what gets handled by something else (e.g., non-Jetpack viewmodel)?
How do we handle navigation, now that we are navigating between functions? Is Navigation for Compose the “one true” navigation solution, or will we wind up switching to something else?
How do we organize our composables into modules, both for stacks that rely upon modules (e.g., Kotlin/Multiplatform) and for basic Android apps?
…and those are just a few that I thought of off the top of my (balding) head.
Tastes will change. The solutions that we use today will look dated tomorrow.
So, in many ways, the biggest thing that you can do is to try to be less opinionated about your own opinions. “Future you” may disagree with your opinions from today, and those opinions will drive a lot of your implementation decisions.
We have no way of predicting the exact nature of the changes that will happen. We can predict that the changes will happen. The more you can do to be able to adapt to those changes — such as writing good tests — the better off you will be when those changes come about.
And now, if you will excuse me, I need to go see what patterns changed while I was writing this newsletter issue… 😁
- 2021-07-20: rc02! Preview and ViewModel, together again! Coil supports Compose! MVI! @dequesystems on accessibility! Screenshots of composables! D-pad support! And... Context code smells?!?
- 2021-07-13: Focus! Viewports! Navigation! @divyajain2405 talks about architecture! Screenshot testing! Sliders! Reorderable lists!
- 2021-07-06: RC01! Navigation! Phones *and* tablets! Cards! Timers! Barcodes! And... the