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

It Just Works

D8a3623b157508fecdae1f8e756f362f?s=47 cmota
November 12, 2021

It Just Works

These last years had been really exciting for app development. First, Android developers moved to Kotlin, then we had Kotlin Multiplatform where we managed to have our app’s business logic shared across iOS and desktop. Now with Compose we can go even further and reuse the UI. In this talk, I’m going to show you can create a library and the UI for your Android application and share it across a Desktop app and the web - it just works*.

D8a3623b157508fecdae1f8e756f362f?s=128

cmota

November 12, 2021
Tweet

More Decks by cmota

Other Decks in Technology

Transcript

  1. Photo by FarawayPictures on deviantART @cafonsomota IT JUST WORKS* (*RUNNING

    COMPOSE ON ANDROID, DESKTOP, AND THE WEB ALONG WITH KMP)
  2. 👨💻 Android GDE 🗣 Founder @GDGCoimbra and co-founder @Kotlin_Knights ✍

    Author @rwenderlich 🗺 Loves travel, photography and running 🍻 Looking to taste a Moretti with all of you @cafonsomota
  3. 🖥 Slides speakerdeck.com/cmota/it-just-works 👉 Code github.com/cmota/alicerce github.com/cmota/unsplash 🍿 YouTube bit.ly/cmota-youtube

    Materials @cafonsomota
  4. A Brief history of Time

  5. 2008 2012 2018 2013 2011 2017 2006 2010 2009 2015

    * Kotlin Multiplatform * @cafonsomota Mobile
  6. 1996 2006 2018 2013 2017 1995 * * Kotlin Multiplatform

    Desktop 2008 @cafonsomota
  7. 2012 2018 2014 2017 2006 2010 2009 2015 * *

    Kotlin Multiplatform Web @cafonsomota
  8. myths of native, hybrid, and cross platform solutions

  9. droiders 🤖 @cafonsomota

  10. I’ve got a new app idea! droiders 🤖 @cafonsomota

  11. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 @cafonsomota
  12. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS @cafonsomota
  13. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! @cafonsomota
  14. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform! @cafonsomota
  15. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform! I’ve been using react native and it’s great! @cafonsomota
  16. Great!! Are you going to do it natively? I’ve got

    a new app idea! droiders 🤖 📱 Natively? You can use Xamarin and instead of android only, you get android and iOS For that, you should use Flutter! It has better performance! But it uses Dart! You’re already familiar with Kotlin, you should try Kotlin Multiplatform! I’ve been using react native and it’s great! 12 people are typing @cafonsomota
  17. How to develop an application?

  18. How to decide? Team background and size Which language is

    your team familiar with? Do they want to learn new things? Can you have developers focused on each platform you’re targeting? Project type Are you developing an MVP? 1yr long project? 5yr? Never ending project? Constraints Time: It hasn’t started yet, and you’re already behind schedule? Budget: Can you hire/allocate more people? @cafonsomota
  19. Framework dependent OS updates require the fw to be updated

    and launch a new app Missing features OS/device features depend on the fw support, you might need to write them Slower performance Commitment to one framework Common disadvantages @cafonsomota
  20. How to develop an application? Spoilers

  21. How to develop an application?

  22. It’s Kotlin ❤ Take advantage of all the language features

    (that you’re already familiar with) Low risk Decide what’s worth to share across platforms Consistency across platforms One tech-stack Strong community support KOtlin Multiplatform @cafonsomota
  23. Kotlin Multiplatform

  24. Kotlin Multiplatform shares your business logic @cafonsomota

  25. presentation presentation presentation presentation model model model model parser parser

    parser parser view network view network view network view network desktop web iOS android @cafonsomota
  26. business logic business logic business logic model parser network presentation

    model parser network presentation model parser network presentation model parser network presentation business logic view view view view desktop web iOS android @cafonsomota
  27. android iOS desktop model parser network presentation common view view

    view view java/kotlin objective-c/ swift (kotlin) JS supported in jvm web @cafonsomota
  28. Kotlin Multiplatform: Platform Specific Code src/commonMain/sample/Platform.kt expect object Platform {

    val name: String } :shared @cafonsomota
  29. src/commonMain/sample/Platform.kt expect object Platform { val name: String } You

    need to de fi ne actual per target actual for Android actual for Desktop actual for JS Kotlin Multiplatform: Platform Specific Code :shared @cafonsomota
  30. src/commonMain/sample/Platform.kt expect object Platform { val name: String } src/androidMain/sample/Platform.kt

    actual object Platform { actual val name: String = "android" } Kotlin Multiplatform: Platform Specific Code :shared @cafonsomota
  31. src/commonMain/sample/Platform.kt expect object Platform { val name: String } src/androidMain/sample/Platform.kt

    actual object Platform { actual val name: String = “android” } Kotlin Multiplatform: Platform Specific Code :shared @cafonsomota
  32. src/commonMain/sample/Platform.kt :shared expect object Platform { val name: String }

    src/androidMain/sample/Platform.kt src/desktopMain/sample/Platform.kt src/webMain/sample/Platform.kt actual object Platform { actual val name: String = “android” } actual object Platform { actual val name: String = “desktop” } actual object Platform { actual val name: String = “web” } Kotlin Multiplatform: Platform Specific Code @cafonsomota
  33. *.kt common expect JVM actual *.kt, *.java, *.jar Native *.kt,

    *C, Swift, Framework JS *.kt, *.js, NPM actual actual
  34. How to develop an application?

  35. Compose

  36. developer.android.com/jetpack/compose

  37. Compose

  38. 🤔 Compose

  39. Jetpack Compose compose.animation compose.material compose.foundation compose.ui compose.runtime compose.compiler

  40. Jetpack Compose compose.animation compose.material compose.foundation compose.ui compose.runtime compose.compiler Compose Compiler

    Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  41. Jetpack Compose compose.animation compose.material compose.foundation compose.ui compose.runtime compose.compiler Compose Compiler

    Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  42. Compose Compiler Compose Runtime Compose UI Toolkit (Android) Compose Animation

    Compose UI Compose Foundation Compose Material Compose compiler android.googlesource.com/platform/frameworks/support/+/HEAD/compose/compiler Written in Kotlin Transforms @Composable into UI Doesn’t use the Annotation Processor The plugin works at system/code generation level Doesn’t impact build times Open source Available in the AOSP
  43. Compose Runtime Platform agnostic Doesn’t know what Android or UI

    are Tree management solution Compose Compiler Compose Runtime Compose UI Toolkit (Android) Compose Animation Compose UI Compose Foundation Compose Material
  44. Compose UI Toolkit Compose Compiler Compose Runtime Compose UI Toolkit

    (Android) Compose Animation Compose UI Compose Foundation Compose Material compose.ui Handles input management, Drawing, Layouts, etc. compose.foundation Contains Basic building: Column, Text, Image, etc. compose.material Material design system to use on components compose.animation Animations to use easily and out side of the box
  45. Compose UI Raspberry pi Compose Compiler Compose Runtime Compose UI

    Android Compose UI Desktop Compose UI Web Compose UI Console Compose
  46. blog.jetbrains.com/kotlin/2021/10/compose-multiplatform-goes-beta/

  47. Android, desktop, and Web

  48. @cafonsomota :androidApp

  49. :androidWearApp

  50. @cafonsomota :desktopApp

  51. :webApp

  52. Now that we’ve got the android app ready, How quickly

    can we have desktop and web apps? - all the dreamers out there
  53. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! @cafonsomota
  54. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! 👉 @cafonsomota
  55. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! 👉 @cafonsomota
  56. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! 👉 @cafonsomota
  57. Kotlin Multiplatform shares your business logic Compose shares your (native)

    UI @cafonsomota
  58. Kotlin Multiplatform shares your business logic Compose shares your (native)

    UI @cafonsomota
  59. KOtlin Multiplatform: Targets jvm JS android android 
 NDK iOS

    watchOS tvOS macOS Linux Windows Web Assembly @cafonsomota
  60. KOtlin Multiplatform: Libraries Kotlinx.x Coroutines, serialization, datetime, atomicfu, etc. Network

    Ktor: github.com/ktorio/ktor Storage Database: github.com/cashapp/sqldelight Others Curated list: github.com/AAkira/Kotlin-Multiplatform-Libraries @cafonsomota
  61. How to Start?

  62. KOtlin Multiplatform: Creating a new KMM project 1. Install the

    KMM plugin on Android Studio 2. Create a new KMM Application ⚠ There’s a version that supports Mac M1 :shared :shared @cafonsomota
  63. KOtlin Multiplatform: Project Structure androidApp/ iosApp/ shared/ :shared @cafonsomota

  64. KOtlin Multiplatform: Project Structure androidApp/ iosApp/ shared/ :shared @cafonsomota

  65. KOtlin Multiplatform: Project Structure androidApp/ iosApp/ shared/ :shared @cafonsomota

  66. KOtlin Multiplatform: Project Structure androidApp/ desktopApp/ webApp/ shared/ :shared @cafonsomota

  67. KOtlin Multiplatform: Project Structure androidApp/ desktopApp/ webApp/ shared/ :shared @cafonsomota

  68. androidApp/ desktopApp/ webApp/ shared/ KOtlin Multiplatform: Project Structure androidMain/ commonMain/

    iosMain/ :shared @cafonsomota
  69. androidApp/ desktopApp/ webApp/ shared/ KOtlin Multiplatform: Project Structure your common

    code (logic) androidMain/ commonMain/ desktopMain/ jsMain/ :shared @cafonsomota
  70. androidApp/ desktopApp/ webApp/ shared/ KOtlin Multiplatform: Project Structure your platform

    speci fi c code (engine, drivers, etc.) :shared androidMain/ commonMain/ desktopMain/ jsMain/ @cafonsomota
  71. KOtlin Multiplatform: Adding new Targets kotlin {a android() iOS()1 }b

    shared/build.gradle.kts :shared
  72. shared/build.gradle.kts KOtlin Multiplatform: Adding new Targets kotlin {a android() jvm("desktop")

    js(IR) {c browser() binaries.executable() }d }b :shared
  73. shared/build.gradle.kts KOtlin Multiplatform: Refactoring to KMP kotlin { ... sourceSets

    { val commonMain by getting dependencies implementation(“io.ktor:ktor-client-core:1.6.4") val androidMain by getting dependencies implementation("io.ktor:ktor-client-android:1.6.4") val desktopMain by getting val jsMain by getting dependencies implementation("io.ktor:ktor-client-js:1.6.4") } } Network ✅ Migrating to Ktor :shared
  74. shared/build.gradle.kts ✅ Migrating to SQLDelight KOtlin Multiplatform: Refactoring to KMP

    kotlin { ... sourceSets { val commonMain by getting val androidMain by getting dependencies implementation("com.squareup.sqldelight:android-driver:1.5.1") val desktopMain by getting dependencies implementation("com.squareup.sqldelight:native-driver:1.5.1") val jsMain by getting dependencies implementation("com.squareup.sqldelight:sqljs-driver:1.5.1") } } :shared
  75. kotlin { ... sourceSets { val commonMain by getting dependencies

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") val androidMain by getting val desktopMain by getting val jsMain by getting } } shared/build.gradle.kts ✅ Migrating to kotlinx.serialization KOtlin Multiplatform: Refactoring to KMP :shared
  76. kotlin { ... sourceSets { val commonMain by getting dependencies

    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.0") val androidMain by getting val desktopMain by getting val jsMain by getting } } shared/build.gradle.kts ✅ Migrating to kotlinx.serialization KOtlin Multiplatform: Refactoring to KMP shared module And of course, Also migratE the API Calls
  77. Do I need to refactor The entire Project?

  78. Do I need to refactor The entire Project? NO

  79. KOtlin Multiplatform You don’t need to commit your entire codebase

    to KMP The goal is to share your business logic Di ff erent apps share di ff erent parts of their code - what makes sense to them! Space *Adapted from: KotlinConf 2019: Opening Keynote by Andrey Breslav Full KMP Cash App Shares: business logic Yandex Maps Shares: business logic, wrappers for C++ libraries PlanGrid Planboard Workspace Shares: business logic, sync logic, mgmnt o ffl ine data Shares: business logic Shares: business logic, networking, o ffl ine caching lyrs
  80. KOtlin Multiplatform: ‘Suggestions’ Start small You’re going to develop a

    new feature? There’s part of your app that needs to be refactored? Want to improve your test coverage? why not do it on the shared module? @cafonsomota
  81. What ‘challenges’ will you find?

  82. KOtlin Multiplatform: ‘Challenges’ 🟡 Not all libraries are available on

    KMP Those who are might not support all targets They might not be compatible with your Kotlin version @cafonsomota
  83. KOtlin Multiplatform: ‘Challenges’ 🟡 Not all libraries are available for

    KMP Those who are might not support all targets They might not be compatible with your Kotlin version 🟠 Project initial setup requires some time Invalidate cache and restart is needed sometimes to recover code auto-complete There are properties that you need to con fi gure: export (iOS), @JsName (JS), etc. Especially when targeting Web, you should enable the IR compiler @cafonsomota
  84. KOtlin Multiplatform: ‘Challenges’ 🟡 Not all libraries are available for

    KMP Those who are might not support all targets They might not be compatible with your Kotlin version 🟠 Project initial setup requires some time Invalidate cache and restart is needed sometimes to recover code auto-complete There are properties that you need to con fi gure: export (iOS), @JsName (JS), etc. Especially when targeting Web, you should enable the IR compiler 🔴 Generated library might need to lose some weight Especially when targeting Web, they can easily gain several MB’s @cafonsomota
  85. Kotlin Multiplatform shares your business logic Compose shares your (native)

    UI @cafonsomota
  86. How to Start?

  87. Compose: Getting Ready If you’re starting Compose for the fi

    rst time Start by developing fi rst on Android Once done, you can move it to a shared module If you’re already familiar with it Create a shared-ui module that will de fi ne the UI for the di ff erent platforms @cafonsomota
  88. Compose: Getting Ready 1. Create a new module called shared-ui

    2. You can just copy-paste shared Rename it to shared-ui Remove all of it’s .kt classes @cafonsomota
  89. Compose To share your Compose UI you’ll need to do

    a bit of KMP Di ff erent platforms, mean di ff erent behaviours For instance, you can resize a window on the desktop but not on your phone* You have di ff erent input types, etc. * well, you can have the app in split screen mode, yes 🙂 @cafonsomota
  90. Compose Compose for Android androidx.compose @cafonsomota

  91. Compose Compose for Android androidx.compose Compose for Desktop/Web org.jetbrains.compose @cafonsomota

  92. Compose src/shared-ui/build.gradle.kts :shared-ui plugins { kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-beta5" id("com.android.library")

    kotlin("plugin.serialization") }
  93. Compose src/shared-ui/build.gradle.kts :shared-ui plugins { kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-beta5" id("com.android.library")

    kotlin("plugin.serialization") } kotlin { ... sourceSets { val commonMain by getting { dependencies { api(compose.foundation) api(compose.runtime) api(compose.foundation) api(compose.material) api(compose.materialIconsExtended) api(compose.ui) api(compose.uiTooling) } } } }
  94. Compose 💥 Duplicated class androidx.compose.* ... BUILD FAILED @cafonsomota

  95. Compose You’re using two di ff erent versions of Compose

    androidx.compose org.jetbrains.compose @cafonsomota
  96. Compose src/androidApp/build.gradle.kts :androidApp plugins { id("org.jetbrains.compose") version “1.0.0-beta5" id("com.android.application") kotlin("android")

    }
  97. Do I need to refactor The entire Project?

  98. Do I need to refactor The entire Project? NO

  99. Compose Compose is interoperable with XML You don’t need to

    rewrite your entire app with Compose You’ll only be able to share the features that are using Compose @cafonsomota
  100. What ‘challenges’ will you find?

  101. Compose: ‘Challenges’ 🟠 Initial setup is… challenging You’ll need to

    use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes @cafonsomota
  102. Compose: ‘Challenges’ 🟠 Initial setup is… challenging You’ll need to

    use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes 🟠 Libraries depend on the Compose version You’ll need to use a compatible one @cafonsomota
  103. Compose: ‘Challenges’ 🟠 Initial setup is… challenging You’ll need to

    use JetBrains Compose plugin Adding the wrong con fi guration might increase building times in several minutes 🟠 Libraries depend on the Compose version You’ll need to use a compatible one 🟠 Not all features are available for Desktop/ Web There’s no direct support for i18n, fonts and other resources LiveData, ViewModels, etc. are only available through third-party libraries @cafonsomota
  104. Compose: ‘Challenges’ 🔴 Web… is in it’s initial stages Not

    all Compose functions are ported to the Web The ones that are, often require that you use DOM elements to manipulate them Adding this abstraction manually will be really time consuming @cafonsomota
  105. How to Solve them

  106. Compose: ‘Challenges’ Accompanist A set of libraries that provide Compose

    ready features Examples: Insets, Paging, Permissions, Swipe to refresh, etc. 📐 Insets 🍫 System UI Controller 🎨 AppCompat Theme Adapter 🧭✨Navigation-Animation 📫 Permissions ⏳ Placeholder 🌊 Flow Layouts 🧭🎨 Navigation-Material 🖌 Drawable Painter ⬇ Swipe to Refresh 📖 Pager @cafonsomota
  107. Accompanist A set of libraries that provide Compose ready features

    Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Compose: ‘Challenges’
  108. Accompanist A set of libraries that provide Compose ready features

    Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Not all Compose libraries are supported on Desktop and Web… for now! Compose: ‘Challenges’
  109. Compose: ‘Challenges’ Accompanist A set of libraries that provide Compose

    ready features Examples: Insets, Paging, Permissions, Swipe to refresh, etc. Not all Compose libraries are supported on Desktop and Web… for now! Community to the rescue! 🚀
  110. Accompanist (by Syer10) A subset of accompanist libraries ported by

    Syer10 to Desktop Available at: syer10.github.io/accompanist Compose: ‘Challenges’
  111. Accompanist (by Syer10) A subset of accompanist libraries ported by

    Syer10 to Desktop Available at: syer10.github.io/accompanist ⚠ only works on Desktop Compose: ‘Challenges’
  112. Compose: ‘Challenges’ Accompanist (by Syer10) A subset of accompanist libraries

    ported by Syer10 to Desktop Available at: syer10.github.io/accompanist ⚠ only works on Desktop Why? 😭
  113. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version "1.0.0-alpha3" } kotlin { api(compose.material)

    api(compose.ui) } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  114. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version "1.0.0-alpha3" } kotlin { api(compose.material)

    api(compose.ui) } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’ ⚠ Not exported to Android
  115. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    api(compose.material) api(compose.ui) }b Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  116. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop") }d Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  117. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop”)e sourceSets {f val commonMain by getting {g dependencies {h api(compose.material) api(compose.ui) }i }j val androidMain by getting val desktopMain by getting }d Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  118. plugins {1 kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") }2 kotlin {a

    android {b publishLibraryVariants("release", “debug") }c jvm(“desktop”)e sourceSets {f val commonMain by getting {g dependencies {h api(compose.material) api(compose.ui) }i }j val androidMain by getting val desktopMain by getting }d android { compileSdk = 31 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 21 targetSdk = 31 } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’
  119. plugins { kotlin("multiplatform") id("org.jetbrains.compose") version “1.0.0-alpha3" id("com.android.library") } kotlin {

    android { publishLibraryVariants("release", “debug") } jvm(“desktop") sourceSets { val commonMain by getting { dependencies { api(compose.material) api(compose.ui) } } val androidMain by getting val desktopMain by getting } android { compileSdk = 31 sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml") defaultConfig { minSdk = 21 targetSdk = 31 } compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 } } Syer10 Accompanist Syer10/accompanist/build.gradle.kts Compose: ‘Challenges’ ✅ Supports Android and Desktop
  120. Compose: Image Loading Coil-Compose Image loading library implemented in Kotlin

    (and using Coroutines) @cafonsomota
  121. Compose: Image Loading Coil-Compose Image loading library implemented in Kotlin

    (and using Coroutines) Not all Compose libraries are supported on Desktop and Web… for now?
  122. Not all Compose libraries are supported on Desktop and Web…

    for now? Compose: Image Loading Coil-Compose Image loading library implemented in Kotlin (and using Coroutines) Community to the rescue! 🚀
  123. Compose: Image Loading Kamel Asynchronous media loading library for Android

    and Desktop Uses Ktor in the background Get it from: github.com/alialbaali/Kamel @cafonsomota
  124. Compose: Image Loading val request = ImageRequest.Builder(LocalContext.current) .data(url) .crossfade(true) .build()

    val painter = rememberImagePainter(request) when (val resource = lazyPainterResource(url)) { is ImagePainter.Loading -> { AddImagePreviewLoading(modifier) } is ImagePainter.Success -> { Image( painter = painter, contentScale = ContentScale.Crop, contentDescription = "Image preview", modifier = modifier) } is ImagePainter.Failure -> { AddImagePreviewFailure(modifier) } Coil
  125. Compose: Image Loading when (val resource = lazyPainterResource(url)) { is

    Resource.Loading -> { AddImagePreviewLoading(modifier) } is Resource.Success -> { KamelImage( resource = resource, contentScale = ContentScale.Crop, contentDescription = "Image preview", modifier = modifier, crossfade = true ) } is Resource.Failure -> { AddImagePreviewFailure(modifier) } Kamel
  126. Compose: Resources Resources Imagine that you want to show an

    image @cafonsomota
  127. Compose: Resources Resources Imagine that you want to show an

    image Hello world!
  128. Compose: Resources Resources Imagine that you want to show an

    image Hello world! Image( painter = painterResource(id = R.drawable.ic_launcher), contentDescription = stringResource(id = R.string.app_name) )
  129. Compose: Resources Resources Imagine that you want to show an

    image Implementation shared-ui/commonMain contains the expect implementation shared-ui/androidMain contains the xml fi les (vectors) and actual implementation shared-ui/desktopMain contains the images (png’s) and actual implementation @cafonsomota
  130. @Composable public expect fun icAbout(): Painter @Composable public expect fun

    icHome(): Painter Resources: Images shared-ui/commonMain/Icons.kt Compose: Resources
  131. @Composable public actual fun icAbout() = painterResource(R.drawable.ic_about) @Composable public actual

    fun icHome() = painterResource(R.drawable.ic_home) Resources: Images shared-ui/androidApp/Icons.kt Compose: Resources
  132. @Composable public actual fun icAbout() = painterResource("images/ic_about.png") @Composable public actual

    fun icHome() = painterResource("images/ic_home.png") Resources: Images shared-ui/desktopApp/Icons.kt Compose: Resources
  133. Compose: Resources Resources Imagine that you want to set a

    custom font @cafonsomota
  134. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! Hello world!
  135. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! Text( text = “Hello World!”, style = typography.h4 ) Hello world!
  136. Compose: Resources Resources Imagine that you want to set a

    custom font Hello world! private val HollywoodHillsFontFamily = FontFamily( Font(R.font.sf_hollywood_hills) ) h4 = TextStyle( color = colorAccent, fontFamily = HollywoodHillsFontFamily, fontSize = fontSizeLarge ) Hello world!
  137. Compose: Resources Resources Imagine that you want to set a

    custom font Implementation shared-ui/commonMain/resources contains the font fi les shared-ui/commonMain/platform de fi nes the expect function shared-ui/androidMain/platform de fi nes the actual function shared-ui/desktopMain/platform de fi nes the actual function @cafonsomota
  138. @Composable expect fun Font( name: String, res: String ): Font

    Resources: Font shared-ui/commonMain/platform/PlatformFont.kt Compose: Resources
  139. @Composable actual fun Font( name: String, res: String, ): Font

    { val context = LocalContext.current val id = context.resources.getIdentifier(res, "font", context.packageName) return Font(id) } Resources: Font shared-ui/androidMain/platform/PlatformFont.kt Compose: Resources
  140. @Composable actual fun Font( name: String, res: String ): Font

    { androidx.compose.ui.text.platform.Font("font/$res.ttf") } shared-ui/desktopMain/platform/PlatformFont.kt Resources: Font Compose: Resources
  141. Compose: Lifecycle, ViewModel, LiveData and Navigation PreCompose (by Tlaster) Lifecycle,

    ViewModel, LiveData and Navigation are Android components They now have been ported to Compose desktop Get it from: github.com/Tlaster/PreCompose
  142. Compose: WebApp What about Web? @cafonsomota

  143. Compose: WebApp What about Web? Is in an initial stage

    and the paradigm is di ff erent It’s focused on DOM rendering Only a set of components are available: Box, Button, Column, Row, Slider, Text @cafonsomota
  144. Compose: WebApp Div({ style { position(Position.Relative) width(100.percent) height(400.px) flexGrow(1.0) marginBottom(10.px)

    } }) { Image(resource = image) } :webApp
  145. Compose: WebApp @Composable fun Column(content: @Composable () -> Unit) {

    Div({ style { display(DisplayStyle.Flex) alignItems(AlignItems.Center) flexGrow(1.0) } }) { content() } } :webApp webApp/components/Column.kt
  146. Compose: WebApp Sharing logic Works without any issue The generated

    JS fi le might be up to several MBs Sharing UI It’s going to be time consuming to share everything You’re going to need to create several components Most of the libraries don’t support it (yet) Nevertheless… it’s fun to see how long we’ll be able to go in a couple of months! @cafonsomota
  147. Getting everything together

  148. Status 🟢 Kotlin Multiplatform Mobile is stable-ish Can be used

    in production although part of it is in alpha/beta 🟢 Compose (Android) is stable Go on! It’s time to dive-in into declarative UI 🟡 Compose (Desktop) is alpha-ish 🔴 Compose (Web) is alpha 🟠 Documentation and samples 🟢 Community and support @cafonsomota
  149. Resources

  150. Jetpack Compose samples (Google) github.com/android/compose-samples Jetpack Compose samples (JetBrains) https://github.com/JetBrains/compose-jb/

    Jetpack/JetBrains Compose Playground foso.github.io/Jetpack-Compose-Playground/ Jetpack Compose Internals Kotlin Slack Resources @cafonsomota
  151. There’s one more thing?

  152. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! 👉 @cafonsomota
  153. SELECT YOUR LEVEL I just want to see the story.

    I want a lighter experience. Give me the full challenge! 👉 @cafonsomota
  154. Kotlin Multiplatform and Compose template Alicerce In Portuguese alicerce means

    foundation A Kotlin Multiplatform with Compose template Currently supports: Android and Desktop Contains an initial project con fi guration along with the libraries mentioned here Open to feedback and contributions! Alicerce
  155. Photo by FarawayPictures on deviantART @cafonsomota IT JUST WORKS* (*RUNNING

    COMPOSE ON ANDROID, DESKTOP, AND THE WEB ALONG WITH KMP)