Slide 1

Slide 1 text

Márton Braun Developer Advocate Blazing Fast UI Development with

Slide 2

Slide 2 text

Demo

Slide 3

Slide 3 text

Setup !// build.gradle.kts plugins { id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha11" }

Slide 4

Slide 4 text

Setup !// build.gradle.kts plugins { id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha11" } !// settings.gradle.kts plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" }

Slide 5

Slide 5 text

Setup !// build.gradle.kts plugins { id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha11" } !// settings.gradle.kts plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } !// Default in Kotlin 2.2.0 composeCompiler { featureFlags.add(ComposeFeatureFlag.OptimizeNonSkippingGroups) }

Slide 6

Slide 6 text

Setup !// build.gradle.kts plugins { id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha11" } !// settings.gradle.kts plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } !// Default in Kotlin 2.2.0 composeCompiler { featureFlags.add(ComposeFeatureFlag.OptimizeNonSkippingGroups) }

Slide 7

Slide 7 text

How does it work? Your app’s code Java Runtime Gradle

Slide 8

Slide 8 text

How does it work? Your app’s code JetBrains Runtime Gradle

Slide 9

Slide 9 text

Setup !// build.gradle.kts plugins { id("org.jetbrains.compose.hot-reload") version "1.0.0-alpha11" } !// settings.gradle.kts plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } !// Default in Kotlin 2.2.0 composeCompiler { featureFlags.add(ComposeFeatureFlag.OptimizeNonSkippingGroups) }

Slide 10

Slide 10 text

How does it work? Your app’s code JetBrains Runtime Gradle

Slide 11

Slide 11 text

Your app’s code JetBrains Runtime Gradle DCEVM How does it work?

Slide 12

Slide 12 text

How does it work? Your app’s code JetBrains Runtime Gradle Hot Reload Agent Recompiler

Slide 13

Slide 13 text

Gradle Recompiler Your app’s code JetBrains Runtime Gradle Hot Reload Agent How does it work?

Slide 14

Slide 14 text

Gradle Recompiler Your app’s code JetBrains Runtime Gradle Hot Reload Agent How does it work?

Slide 15

Slide 15 text

How does it work? Gradle Recompiler Your app’s code JetBrains Runtime Gradle Hot Reload Agent DCEVM

Slide 16

Slide 16 text

How does it work? Gradle Recompiler Your app’s code JetBrains Runtime Gradle Hot Reload Agent

Slide 17

Slide 17 text

How does it work? Gradle Recompiler Your app’s code JetBrains Runtime Gradle Hot Reload Agent

Slide 18

Slide 18 text

How does it work? Gradle Recompiler Dev Tooling Your app’s code JetBrains Runtime Gradle Hot Reload Agent

Slide 19

Slide 19 text

How does it work? Gradle Recompiler Dev Tooling Your app’s code JetBrains Runtime Gradle Hot Reload Agent

Slide 20

Slide 20 text

How does it work? Gradle Recompiler Dev Tooling Your app’s code JetBrains Runtime Gradle Hot Reload Agent

Slide 21

Slide 21 text

How does it work? Gradle Recompiler Dev Tooling Your app’s code JetBrains Runtime Gradle Hot Reload Agent IDE

Slide 22

Slide 22 text

DCEVM Dynamic Code Evolution Virtual Machine class Offset( val x: Int, ) Current Class Loader

Slide 23

Slide 23 text

DCEVM class Offset( val x: Int, val y: Int, ) Dynamic Code Evolution Virtual Machine Side Universe Class Loader class Offset( val x: Int, ) Current Class Loader

Slide 24

Slide 24 text

DCEVM class Offset( val x: Int, val y: Int, ) Dynamic Code Evolution Virtual Machine Current Class Loader

Slide 25

Slide 25 text

What do you mean… “migrate objects”?

Slide 26

Slide 26 text

DCEVM Dynamic Code Evolution Virtual Machine Offset@235235 Offset@534643 Offset@734122 Of class Offset( val x: Int, )

Slide 27

Slide 27 text

DCEVM Dynamic Code Evolution Virtual Machine 42 Header 13 Header 24 Header Offset@235235 Offset@534643 Offset@734122 Of class Offset( val x: Int, )

Slide 28

Slide 28 text

DCEVM Dynamic Code Evolution Virtual Machine 42 Header 13 Header 24 Header Offset@235235 Offset@534643 Offset@734122 Of class Offset( val x: Int, val y: Int, ) +

Slide 29

Slide 29 text

DCEVM Dynamic Code Evolution Virtual Machine 42 Header 13 Header 24 Header Offset@235235 Offset@534643 Offset@734122 Of Offset@235235 Offset@534643 Offset@734 class Offset( val x: Int, val y: Int, ) +

Slide 30

Slide 30 text

DCEVM Dynamic Code Evolution Virtual Machine 42 Header 13 Header 24 Header Offset@235235 Offset@534643 Offset@734122 Of Offset@235235 Offset@534643 Offset@734 42 Header 13 Header Head class Offset( val x: Int, val y: Int, ) +

Slide 31

Slide 31 text

DCEVM Dynamic Code Evolution Virtual Machine 42 Header 13 Header 24 Header Offset@235235 Offset@534643 Offset@734122 Of Offset@235235 Offset@534643 Offset@734 42 Header 13 Header Head 0 0 class Offset( val x: Int, val y: Int, ) +

Slide 32

Slide 32 text

DCEVM Dynamic Code Evolution Virtual Machine Offset@235235 Offset@534643 Offset@734 42 Header 13 Header Head 0 0 class Offset( val x: Int, val y: Int, ) +

Slide 33

Slide 33 text

Compose diffing fun mediumPadding() = 16.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here's a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } }

Slide 34

Slide 34 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here's a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 35

Slide 35 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here's a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 36

Slide 36 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here's a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 37

Slide 37 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here's a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 38

Slide 38 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here’s a counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 39

Slide 39 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here’s a wonderful counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 40

Slide 40 text

fun mediumPadding() = 32.dp @Composable fun Counter() { var counter by remember { mutableStateOf(0) } Text("Here’s a wonderful counter:") Card { Button( modifier = Modifier.padding(mediumPadding()), onClick = { counter++ } ) { Text("Clicked $counter times") } } } Compose diffing

Slide 41

Slide 41 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") } } } }

Slide 42

Slide 42 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") } } } } CS$SomeWidgetKt$lambda-1.class Function3

Slide 43

Slide 43 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") } } } } CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function3

Slide 44

Slide 44 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function3 } } } }

Slide 45

Slide 45 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } } } } } CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function3

Slide 46

Slide 46 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } } } } } CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function3 CS$SomeWidgetKt$lambda-?.class Function2

Slide 47

Slide 47 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } } } } } CS$SomeWidgetKt$lambda-4.class Function3 CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function2

Slide 48

Slide 48 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } } } } } CS$SomeWidgetKt$lambda-4.class Function3 CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function2 this: ColumnScope this: ColumnScope this: ColumnScope

Slide 49

Slide 49 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } } } } } CS$SomeWidgetKt$lambda-4.class Function3 CS$SomeWidgetKt$lambda-3.class Function3 CS$SomeWidgetKt$lambda-2.class Function3 CS$SomeWidgetKt$lambda-1.class Function2

Slide 50

Slide 50 text

Structural changes CS$SomeWidgetKt$lambda-3523533.class Function3 CS$SomeWidgetKt$lambda-1995335.class Function3 CS$SomeWidgetKt$lambda-1245234.class Function3 CS$SomeWidgetKt$lambda-5235232.class Function2 } } } } @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") }

Slide 51

Slide 51 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") CS$SomeWidgetKt$lambda-3523533.class Function3 CS$SomeWidgetKt$lambda-1995335.class Function3 CS$SomeWidgetKt$lambda-1245234.class Function3 } } } }

Slide 52

Slide 52 text

Structural changes @Composable fun SomeWidget() { Card { Text("A") Card { Text("B") Card { Text("C") Surface { Text("D") } CS$SomeWidgetKt$lambda-3523533.class Function3 CS$SomeWidgetKt$lambda-1995335.class Function3 } } } } CS$SomeWidgetKt$lambda-1245234.class Function3 CS$SomeWidgetKt$lambda-5235232.class Function2

Slide 53

Slide 53 text

Demo

Slide 54

Slide 54 text

jb.gg/chr

Slide 55

Slide 55 text

Yes, you’ll need a desktop target.

Slide 56

Slide 56 text

Android app iOS app Compose Multiplatform UI ViewModels Data layer

Slide 57

Slide 57 text

Desktop app Android app iOS app Compose Multiplatform UI ViewModels Data layer

Slide 58

Slide 58 text

Desktop app* Android app iOS app Compose Multiplatform UI ViewModels Data layer Fake data layer

Slide 59

Slide 59 text

Gallery app Android app iOS app Compose Multiplatform UI ViewModels Data layer

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

No content

Slide 63

Slide 63 text

Kotlin by JetBrains, present and future (office hours) unsolved conf @ 12:00 Márton Braun Sebastian Aigner

Slide 64

Slide 64 text

zsmb.co/talks Márton Braun @zsmb.co Compose Hot Reload jb.gg/chr KotlinConf app jb.gg/kc-app Sebastian Sellmair’s content KotlinConf talk jb.gg/kc25-chr YouTube youtube.com/@s.sellmair Blog blog.sellmair.io Blazing Fast UI Development with