Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Composables under the hood

Thomas Künneth
January 24, 2021
850

Composables under the hood

Building declarative user interfaces with Jetpack Compose is easy and fun. But if you come from imperative frameworks, you are used to certain ways of doing things. For example, custom components can be implemented using drawing primitives. How is this achieved with composables? Also, what about the main thread. Do we still need to take care of this? In this talk I will map imperative best practices to the declarative world. You'll see plenty of examples and running code.

Thomas Künneth

January 24, 2021
Tweet

Transcript

  1. • UI frameworks were long based on components • Components

    are classes or data structures • UI is defined through component trees • in code • with some markup language
  2. • During runtime either object tree or nested data structure

    • To change the ui, we change the component tree
  3. Two main groups of components • Elements users can interact

    with: buttons, checkboxes, textfields • Elements laying out and structuring other elements (usually invisble to the user) Sergey Zolkin, Unsplash (https://unsplash.com/photos/m9qMoh-scfE)
  4. Based on inheritance • UI elements take the mechanics of

    their ancestor and modify or enrich it • Example: Buttons Sean Stratton, Unsplash (https://unsplash.com/photos/ObpCE_X3j6U)
  5. Create custom components • Pick a suitable ancestor and modify

    or enhance it • Works well if one parent provides all needed base functionality The Digital Marketing Collaboration, Unsplash (https://unsplash.com/photos/i0WO_RzeB2Y)
  6. • In Jetpack Compose we also combine building blocks •

    No traditional class-based inheritance • Composables can be polymorph Example: • Just like traditional views, composables are nested (in example Row includes Checkbox and TextField)
  7. • Often composables delegate functionality to generalized versions • For

    example, Checkbox() invokes TriStateCheckbox() • In a way inheritance without OO
  8. • Look and behavior of composables can be configured through

    parameters • Or modifier Ordered, immutable collection of modifier elements
  9. • androidx.compose.ui.Modifier helps define such collections • Both interface and

    companion object • Most important function: then() (implementations can be both simple and complex)
  10. DrawScope creates a scoped drawing environment with the provided Canvas.

    This provides a declarative, stateless API to draw shapes and paths without requiring consumers to maintain underlying Canvas state information.
  11. Modifier companion object can be used as the start of

    a modifier extension factory expression
  12. • factory is • a composable • extension function of

    Modifier • Wrapped in a ComposedModifier and passed to then() • ComposedModifier is a private class • extends abstract InspectorValueInfo • implements Modifier.Element (a single element contained within a Modifier chain)
  13. When to use then() When to use a factory ...?

    If you need no inspectorInfo, direct use of then() might be simpler
  14. drawWithContent() allows you to draw before or after the layout's

    contents Location of drawContent() defines when the content is drawn
  15. • Modifiers amend look or behavior of components • What

    if a component shall not be altered but designed from scratch? • In imperative ui frameworks ui elements share one common root component • It defines all mechanics a ui element must provide • Usually includes • size and location • contract how to represent itself on screen
  16. • Practically all ui frameworks are single- threaded • All

    manipulation of the component tree must be done on a specific thread • This particular thread must never be blocked Adam Griffith, Unsplash (https://unsplash.com/photos/XXuVUrnpi8M)
  17. • Using Jetpack Compose is great fun • As still

    in alpha, expect changes • Look under hood to understand how Compose works