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

Composables under the hood

Thomas Künneth
January 24, 2021

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


  1. Composables under the hood Thomas Künneth GDG DevFest DACH 2021-01-24

  2. https://speakerdeck.com/tkuenneth https://www.thomaskuenneth.eu/ https://github.com/tkuenneth/android-demos @tkuenneth

  3. Agenda • Anatomy of traditional ui frameworks • Modifier •

    Canvas • Threads
  4. Kira auf der Heide, Unsplash (https://unsplash.com/photos/_Zd6COnH5E8) Anatomy of traditional ui

  5. • 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
  6. • During runtime either object tree or nested data structure

    • To change the ui, we change the component tree
  7. 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)
  8. 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)
  9. Takafumi Yamashita, Unsplash (https://unsplash.com/photos/MeiWDyodbSQ) What if no available ui component

    suits your requirements?
  10. 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)
  11. Need features of different components?

  12. None
  13. None
  14. • 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)
  15. • Often composables delegate functionality to generalized versions • For

    example, Checkbox() invokes TriStateCheckbox() • In a way inheritance without OO
  16. None
  17. Modifier Patrick, Unsplash (https://unsplash.com/photos/bWSiIlfFr-8)

  18. • Look and behavior of composables can be configured through

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

    companion object • Most important function: then() (implementations can be both simple and complex)
  20. None
  21. 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.
  22. interface LayoutModifier : Modifier.Element

  23. Modifier companion object can be used as the start of

    a modifier extension factory expression
  24. Returns the result of composed() modifier which receives a factory

    and an inspectorInfo
  25. • 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)
  26. None
  27. When to use then() When to use a factory ...?

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

    contents Location of drawContent() defines when the content is drawn
  29. • 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
  30. Let‘s see how to do this in Compose

  31. Justyn Warner, Unsplash (https://unsplash.com/photos/VH8w75u3LE0) Canvas

  32. None
  33. None
  34. Kelly Sikkema, Unsplash (https://unsplash.com/photos/zEhPw7ZDvNA) Threads

  35. • 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)
  36. John Schnobrich, Unsplash (https://unsplash.com/photos/FlPc9_VocJ4)

  37. vikram sundaramoorthy, Unsplash (https://unsplash.com/photos/0NaeAT9oldM) Wrap up

  38. • Using Jetpack Compose is great fun • As still

    in alpha, expect changes • Look under hood to understand how Compose works
  39. thomas@thomaskuenneth.eu @tkuenneth Thanks a lot for listening!