KEMBAR78
Jetpack Compose - A Lightning Tour | PDF
Jetpack Compose
A lightning tour
GDG Auckland - May 2019
Disclaimer
• I’m not an expert on any of this :)

• This is the result of building the sample, exploring source
code and some reading

• Flutter and React devs - feel free to speak up

• Compose is pre-alpha and not ready for production
What is it?
• A “…modern, reactive style UI toolkit for Android, which takes advantage
of Kotlin and integrates seamlessly with the platform and all of your
existing code.”

• Declarative - “Simply describe your UI as a set of composable functions,
and the framework handles UI optimizations under the hood and
automatic updates to the view hierarchy.”

• Inspired by/similar to Flutter, React, Litho

• Way to allow the Android UI Framework to evolve, unbundled from
platform releases

• Create smaller, reusable UI components by composing lower-level UI
components, e.g.:
Composable UI
components
/**
* The Bills card within the Rally Overview screen.
*/
@Composable
fun RallyBillsCard() {
Card(color = cardInternalColor) {
Column {
Padding(padding = 12.dp) {
Column {
Text(text = "Bills", style = +themeTextStyle { subtitle2 })
Text(text = "$1,810.00", style = +themeTextStyle { h1 })
}
}
}
}
}
Counter app
class CounterActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CraneWrapper {
CounterApp()
}
}
}
@Composable
fun CounterApp() {
val counter = +state { 0 }
MaterialTheme {
Button(onClick = { counter.value++ }) {
Text(text = "Counter = ${counter.value}")
}
}
}
}
Q: Wtf is going on here:

val counter = +state { 0 }
@Composable
fun CounterApp() {
val counter = +state { 0 }
MaterialTheme {
Button(onClick = { counter.value++ }) {
Text(text = "Counter = ${counter.value}")
}
}
}
Q: Wtf is going on here:

val counter = +state { 0 }
@Composable
fun CounterApp() {
val result: Effect<State<Int>> = state { 0 }
val counter: State<Int> = +result
MaterialTheme {
Button(onClick = { counter.value++ }) {
Text(text = "Counter = ${counter.value}")
}
}
}
Q: Are components just implemented
with Fragments/Views?
• No*, widgets are just functions that ultimately make
canvas draw calls.
@Composable
fun ColoredRect(brush: Brush, width: Dp? = null, height: Dp? = null) {
Container(width = width, height = height, expanded = true) {
DrawFillRect(brush = brush)
}
}
@Composable
private fun DrawFillRect(brush: Brush) {
Draw { canvas, parentSize ->
val paint = Paint()
brush.applyBrush(paint)
canvas.drawRect(parentSize.toRect(), paint)
}
}
Tangent: KTX tags (?!)
@Composable
fun Draw(
children: @Composable() () -> Unit = {},
@Children(composable = false)
onPaint: DrawScope.(canvas: Canvas, parentSize: PxSize) -> Unit
) {
// Hide the internals of DrawNode
<DrawNode onPaint={ canvas, parentSize ->
DrawScope(this).onPaint(canvas, parentSize)
}>
children()
</DrawNode>
}
Tangent: KTX tags (?!)
Tangent: KTX tags (?!)
@Composable
fun RallyApp() {
val counter = +state { 0 }
RallyTheme {
Scaffold(appBar = { RallyAppBar() }) {
Padding(padding = 16.dp) {
Button(onClick = { counter.value++ }) {
Text(text = "Counter = ${counter.value}",
style = +themeTextStyle { h3 })
}
}
}
}
}
Tangent: KTX tags (?!)
@Composable
fun RallyApp() {
val counter = +state { 0 }
<RallyTheme>
<Scaffold appBar={ <RallyAppBar /> }>
<Padding padding=16.dp>
<Button onClick={ counter.value++ }>
<Text text="Counter = ${counter.value}"
style=+themeTextStyle { h3 } />
</Button>
</Padding>
</Scaffold>
</RallyTheme>
}
Automatic XML -> KTX
conversion
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello world!"/>
</LinearLayout>
Automatic XML -> KTX
conversion
Automatic XML -> KTX
conversion (kinda…)
Q: Are components just implemented
with Fragments/Views?
• No*, widgets are just functions that ultimately make
canvas draw calls.

• *In practise, you need at least one special View:
AndroidCraneView
• Typically you won’t create this directly, but via
CraneWrapper, e.g.:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
CraneWrapper {
RallyApp()
}
}
}
Q: How do I check it out?
• Short answer - follow this guide: https://medium.com/
q42-engineering/try-jetpack-compose-today-
a12bda50aed2
Q: How do I check it out?
Longer answer:

• Get a Repo client (Google’s VCS)

• Check out the androidx branch of AOSP (~3GB)

• Run a script to DL/build a custom unstable version of
Android Studio (30min+)

• Play with the sample projects
Further Reading/Watching
• Diving into Jetpack Compose - Thijs Suijten

https://medium.com/q42-engineering/android-jetpack-
compose-895b7fd04bf4

• Android Jetpack Compose Review - Karumi. Mentions some
areas for improvement

https://blog.karumi.com/android-jetpack-compose-review/

• Android developers page

https://developer.android.com/jetpack/compose

• Declarative UI Patterns (Google I/O’19)

https://youtu.be/VsStyq4Lzxo
Thank you
Questions, opinions, further thoughts?
Matt Clarke

Twitter: @kiwiandroiddev

Jetpack Compose - A Lightning Tour

  • 1.
    Jetpack Compose A lightningtour GDG Auckland - May 2019
  • 2.
    Disclaimer • I’m notan expert on any of this :) • This is the result of building the sample, exploring source code and some reading • Flutter and React devs - feel free to speak up • Compose is pre-alpha and not ready for production
  • 3.
    What is it? •A “…modern, reactive style UI toolkit for Android, which takes advantage of Kotlin and integrates seamlessly with the platform and all of your existing code.” • Declarative - “Simply describe your UI as a set of composable functions, and the framework handles UI optimizations under the hood and automatic updates to the view hierarchy.” • Inspired by/similar to Flutter, React, Litho • Way to allow the Android UI Framework to evolve, unbundled from platform releases • Create smaller, reusable UI components by composing lower-level UI components, e.g.:
  • 4.
    Composable UI components /** * TheBills card within the Rally Overview screen. */ @Composable fun RallyBillsCard() { Card(color = cardInternalColor) { Column { Padding(padding = 12.dp) { Column { Text(text = "Bills", style = +themeTextStyle { subtitle2 }) Text(text = "$1,810.00", style = +themeTextStyle { h1 }) } } } } }
  • 5.
    Counter app class CounterActivity: Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { CounterApp() } } } @Composable fun CounterApp() { val counter = +state { 0 } MaterialTheme { Button(onClick = { counter.value++ }) { Text(text = "Counter = ${counter.value}") } } } }
  • 6.
    Q: Wtf isgoing on here:
 val counter = +state { 0 } @Composable fun CounterApp() { val counter = +state { 0 } MaterialTheme { Button(onClick = { counter.value++ }) { Text(text = "Counter = ${counter.value}") } } }
  • 7.
    Q: Wtf isgoing on here:
 val counter = +state { 0 } @Composable fun CounterApp() { val result: Effect<State<Int>> = state { 0 } val counter: State<Int> = +result MaterialTheme { Button(onClick = { counter.value++ }) { Text(text = "Counter = ${counter.value}") } } }
  • 8.
    Q: Are componentsjust implemented with Fragments/Views? • No*, widgets are just functions that ultimately make canvas draw calls.
  • 9.
    @Composable fun ColoredRect(brush: Brush,width: Dp? = null, height: Dp? = null) { Container(width = width, height = height, expanded = true) { DrawFillRect(brush = brush) } } @Composable private fun DrawFillRect(brush: Brush) { Draw { canvas, parentSize -> val paint = Paint() brush.applyBrush(paint) canvas.drawRect(parentSize.toRect(), paint) } }
  • 10.
    Tangent: KTX tags(?!) @Composable fun Draw( children: @Composable() () -> Unit = {}, @Children(composable = false) onPaint: DrawScope.(canvas: Canvas, parentSize: PxSize) -> Unit ) { // Hide the internals of DrawNode <DrawNode onPaint={ canvas, parentSize -> DrawScope(this).onPaint(canvas, parentSize) }> children() </DrawNode> }
  • 11.
  • 12.
    Tangent: KTX tags(?!) @Composable fun RallyApp() { val counter = +state { 0 } RallyTheme { Scaffold(appBar = { RallyAppBar() }) { Padding(padding = 16.dp) { Button(onClick = { counter.value++ }) { Text(text = "Counter = ${counter.value}", style = +themeTextStyle { h3 }) } } } } }
  • 13.
    Tangent: KTX tags(?!) @Composable fun RallyApp() { val counter = +state { 0 } <RallyTheme> <Scaffold appBar={ <RallyAppBar /> }> <Padding padding=16.dp> <Button onClick={ counter.value++ }> <Text text="Counter = ${counter.value}" style=+themeTextStyle { h3 } /> </Button> </Padding> </Scaffold> </RallyTheme> }
  • 14.
    Automatic XML ->KTX conversion <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello world!"/> </LinearLayout>
  • 15.
    Automatic XML ->KTX conversion
  • 16.
    Automatic XML ->KTX conversion (kinda…)
  • 17.
    Q: Are componentsjust implemented with Fragments/Views? • No*, widgets are just functions that ultimately make canvas draw calls. • *In practise, you need at least one special View: AndroidCraneView • Typically you won’t create this directly, but via CraneWrapper, e.g.: override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CraneWrapper { RallyApp() } } }
  • 18.
    Q: How doI check it out? • Short answer - follow this guide: https://medium.com/ q42-engineering/try-jetpack-compose-today- a12bda50aed2
  • 19.
    Q: How doI check it out? Longer answer: • Get a Repo client (Google’s VCS) • Check out the androidx branch of AOSP (~3GB) • Run a script to DL/build a custom unstable version of Android Studio (30min+) • Play with the sample projects
  • 20.
    Further Reading/Watching • Divinginto Jetpack Compose - Thijs Suijten
 https://medium.com/q42-engineering/android-jetpack- compose-895b7fd04bf4 • Android Jetpack Compose Review - Karumi. Mentions some areas for improvement
 https://blog.karumi.com/android-jetpack-compose-review/ • Android developers page
 https://developer.android.com/jetpack/compose • Declarative UI Patterns (Google I/O’19)
 https://youtu.be/VsStyq4Lzxo
  • 21.
    Thank you Questions, opinions,further thoughts? Matt Clarke
 Twitter: @kiwiandroiddev