I sometimes hear Compose UI. For example <here> a...
# compose
m
I sometimes hear Compose UI. For example here and there. And Compose UI sounds temptingly nice. Is Compose UI another or a new name for Jetpack Compose?
d
Read this post, it explains things well https://jakewharton.com/a-jetpack-compose-by-any-other-name/
βž• 2
a
Generally: Jetpack Compose => umbrella term for the whole project and stack; the contents of
androidx.compose
and all subpackages and related modules Compose compiler => kotlinc IR plugin Compose runtime => supporting runtime library that handles snapshots and composition+updates of tree data structures Compose UI => A UI toolkit built on top of the Compose compiler+runtime. Defines things like what LayoutNodes and Modifiers are, and how to write input handlers, custom layouts, and drawing. Compose foundation => Design system agnostic building blocks for Compose UI. Rows and columns, lazy lists, recognition of particular gestures, etc. Compose Material => An implementation of the Material Design system for Compose UI, built using Foundation.
πŸ™ 12
m
Oh, I thought Compose material and Compose foundation are part of Compose UI.
a
They're built on top of it
βž• 1
we make this distinction particularly to keep ourselves honest about how we access capabilities between layers. Foundation doesn't do anything with Compose UI that you can't do yourself from your own code. Material doesn't do anything with foundation or compose UI that you can't do from your own code. It's all public API between those layers.
The view system in Android developed a number of private contracts between layers like this that led to things being very difficult to extend or build on from the outside; we're deliberately avoiding repeating that here. πŸ™‚
❀️ 1
(There are even a few capabilities ListView has around view recycling that RecyclerView couldn't do, for example.)
d
Adam, do you think this makes developing Compose easier or harder for you in the long run?
a
Far, far easier.
Those shortcuts in the view system were almost always taken due to a lack of time to get an API right in an Android dessert release schedule and every one of them was tech debt. Some of them we should have just committed to rather than being squeamish about it. (Said with the benefit of hindsight, of course πŸ™ƒ )
πŸ‘ 1
m
So, how can I create a piece of Text with Compose UI without resorting to Foundation or Material?
a
You can but you might not want to, given how much is involved in performing text measurement and layout, populating semantics, supporting selection, etc. πŸ™‚ take a look at the
CoreText
composable for how it's implemented there
πŸ˜… 1
There's a lot you can skip and simplify for some use cases, but things like accessibility are critically important for users
πŸ™ 1
m
So, the Android team could have given us only Compose UI! Then, I guess learning Compose and creating UIs would be quite difficult πŸ˜„
a
well, learning it would be much easier to understand in some ways since there would be fewer parts involved, but it would be very, "here's an ax and a forest, go build your own house" πŸ™‚
❀️ 1
by forcing ourselves to separate out compose UI vs. foundation, we've ensured that it's possible to build your own foundation-like components without having to upstream them to the jetpack compose project itself to have access to internal-only capabilities
so if you don't like something in foundation, you can fork it yourself and be on your way without having to do custom builds of compose
m
So, this adds a myriad of UIs possibilities and creativity too for developers, for example to create various UI libraries on top of Compose UI.
πŸ‘Œ 1
a
the analogous layers in the android framework are
android.view
and
android.widget
, and those had a lot of private comms between them
m
However, mastering custom layouts then would be a necessity I guess.
a
I'm really happy with the custom layout API though πŸ™‚ after writing countless custom ViewGroup layouts over the years, compose UI distills it down really nicely; mastering custom compose ui layouts is a lot easier
m
I'm not sure if I understand what you mean by private comms between android.view and android.widget. You mean, they are using duplicated or common code?
a
the android framework has this "trick" in how we generate the SDK. The SDK is a stubs jar; it doesn't contain real implementations, but it's derived from the on-device framework code so that you can link against it when you build your app.
βž• 1
m
You mean they were tightly coupled in some ways? Unlike Compose UI and Foundation that are kinda independent?
a
There's a magic javadoc tag
@hide
that will omit something from the SDK even if it's declared
public
in the source code
so other things in the framework can treat it as public, but it's not available to apps
when people talk about, "private API" in Android, this is usually what they mean.
βž• 1
so when someone is working on the android framework itself building a high level component, they see all of the "real" public surface of what they're building with; it all autocompletes as normal, etc. there's no difference. It's extremely easy to build high level components that can't be built outside of the framework without realizing that this is the case.
so with compose (and other jetpack libraries too, compose isn't unique in this) we're building more modularly in part to keep this sort of thing from creeping in.
d
so you say deadlines were the primary reason of this "privatizaion" of APIs? Or was it also a lack of some knowledge/understanding?
a
Deadlines+fear and uncertainty, mostly. Since Android never* truly removes APIs from the SDK to not break compatibility with even the oldest apps, adding a platform API is a big deal. There's no breaking 2.0 release, each API level has to be compatible with the one that came before it. So if we weren't sure if we had just the right abstraction we were willing to support ~forever yet, we'd err on the side of caution and
@hide
it.
(* we have been known to actually remove APIs breaking binary compatibility in some very specific circumstances around security/privacy issues, but even then usually we no-op the call internally rather than cause apps that try to call it to crash.)
m
So, Jetpack Compose components do not have any hidden contracts (or comms) with each other. They are standard APIs that can be used to build upon. And furthermore, they are not platform-dependent at all (except the fact that Compose is only supported on API 21+). You also mentioned "...without having to upstream them to the jetpack compose project itself to have access to internal-only capabilities". Do you mean some capabilities defined in a Jetpack Compose module is supposed to be internal to the module and not called from another modules?
a
If we didn't have the layered approach described above, then the only way to write certain kinds of UI component features would be to upstream new public extension point APIs into some existing compose constructs. We run into this with RecyclerView often, for example. RV is too big to practically maintain a fork of, whereas compose components are made up of much smaller public pieces that can be recombined in forks of foundation-level components more easily.
βž• 2
t
As Adam said, we'll have a stack like that. Just replace Engine C++ with Compose Compiler+Runtime.