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

It Just Works

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*.

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)

    View full-size slide

  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

    View full-size slide

  3. 🖥 Slides


    speakerdeck.com/cmota/it-just-works


    👉 Code


    github.com/cmota/alicerce


    github.com/cmota/unsplash


    🍿 YouTube


    bit.ly/cmota-youtube
    Materials
    @cafonsomota

    View full-size slide

  4. A Brief history of Time

    View full-size slide

  5. 2008 2012 2018
    2013
    2011 2017
    2006 2010
    2009 2015
    * Kotlin Multiplatform
    *
    @cafonsomota
    Mobile

    View full-size slide

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

    View full-size slide

  7. 2012 2018
    2014 2017
    2006 2010
    2009 2015
    *
    * Kotlin Multiplatform
    Web
    @cafonsomota

    View full-size slide

  8. myths of


    native, hybrid, and cross
    platform solutions

    View full-size slide

  9. droiders 🤖
    @cafonsomota

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  17. How to develop an
    application?

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  20. How to develop an
    application?
    Spoilers

    View full-size slide

  21. How to develop
    an application?

    View full-size slide

  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

    View full-size slide

  23. Kotlin Multiplatform

    View full-size slide

  24. Kotlin Multiplatform
    shares your business logic
    @cafonsomota

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  28. Kotlin Multiplatform: Platform Specific Code
    src/commonMain/sample/Platform.kt
    expect object Platform {


    val name: String


    }


    :shared
    @cafonsomota

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  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

    View full-size slide

  33. *.kt
    common
    expect
    JVM
    actual
    *.kt, *.java, *.jar
    Native
    *.kt, *C, Swift, Framework
    JS
    *.kt, *.js, NPM
    actual
    actual

    View full-size slide

  34. How to develop
    an application?

    View full-size slide

  35. developer.android.com/jetpack/compose

    View full-size slide

  36. Jetpack Compose
    compose.animation


    compose.material


    compose.foundation


    compose.ui


    compose.runtime


    compose.compiler


    View full-size slide

  37. 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

    View full-size slide

  38. 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

    View full-size slide

  39. 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

    View full-size slide

  40. 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

    View full-size slide

  41. 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

    View full-size slide

  42. Compose UI
    Raspberry pi
    Compose Compiler
    Compose Runtime
    Compose UI
    Android
    Compose UI
    Desktop
    Compose UI
    Web
    Compose UI
    Console
    Compose

    View full-size slide

  43. blog.jetbrains.com/kotlin/2021/10/compose-multiplatform-goes-beta/

    View full-size slide

  44. Android, desktop, and Web

    View full-size slide

  45. @cafonsomota
    :androidApp

    View full-size slide

  46. :androidWearApp

    View full-size slide

  47. @cafonsomota
    :desktopApp

    View full-size slide

  48. Now that we’ve got
    the android app
    ready, How quickly
    can we have desktop
    and web apps?
    - all the dreamers out there

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  55. KOtlin Multiplatform: Targets
    jvm
    JS


    android
    android

    NDK
    iOS
    watchOS
    tvOS
    macOS
    Linux
    Windows
    Web


    Assembly
    @cafonsomota

    View full-size slide

  56. 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

    View full-size slide

  57. How to Start?

    View full-size slide

  58. 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

    View full-size slide

  59. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View full-size slide

  60. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View full-size slide

  61. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View full-size slide

  62. KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared
    @cafonsomota

    View full-size slide

  63. KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared
    @cafonsomota

    View full-size slide

  64. androidApp/


    desktopApp/


    webApp/


    shared/
    KOtlin Multiplatform: Project Structure
    androidMain/


    commonMain/


    iosMain/
    :shared
    @cafonsomota

    View full-size slide

  65. androidApp/


    desktopApp/


    webApp/


    shared/
    KOtlin Multiplatform: Project Structure
    your common code (logic)
    androidMain/


    commonMain/


    desktopMain/


    jsMain/
    :shared
    @cafonsomota

    View full-size slide

  66. androidApp/


    desktopApp/


    webApp/


    shared/
    KOtlin Multiplatform: Project Structure
    your platform speci
    fi
    c code (engine, drivers, etc.)
    :shared
    androidMain/


    commonMain/


    desktopMain/


    jsMain/
    @cafonsomota

    View full-size slide

  67. KOtlin Multiplatform: Adding new Targets
    kotlin {a


    android()


    iOS()1


    }b


    shared/build.gradle.kts
    :shared

    View full-size slide

  68. shared/build.gradle.kts
    KOtlin Multiplatform: Adding new Targets
    kotlin {a


    android()


    jvm("desktop")


    js(IR) {c


    browser()


    binaries.executable()


    }d


    }b
    :shared

    View full-size slide

  69. 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

    View full-size slide

  70. 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

    View full-size slide

  71. 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

    View full-size slide

  72. 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

    View full-size slide

  73. Do I need to
    refactor The entire
    Project?

    View full-size slide

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

    View full-size slide

  75. 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

    View full-size slide

  76. 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

    View full-size slide

  77. What ‘challenges’
    will you find?

    View full-size slide

  78. 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

    View full-size slide

  79. 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

    View full-size slide

  80. 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

    View full-size slide

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

    View full-size slide

  82. How to Start?

    View full-size slide

  83. 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

    View full-size slide

  84. 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

    View full-size slide

  85. 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

    View full-size slide

  86. Compose
    Compose for Android


    androidx.compose


    @cafonsomota

    View full-size slide

  87. Compose
    Compose for Android


    androidx.compose


    Compose for Desktop/Web


    org.jetbrains.compose


    @cafonsomota

    View full-size slide

  88. 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")


    }


    View full-size slide

  89. 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)


    }


    }


    }


    }


    View full-size slide

  90. Compose
    💥 Duplicated class androidx.compose.*


    ...

    BUILD FAILED


    @cafonsomota

    View full-size slide

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


    androidx.compose


    org.jetbrains.compose


    @cafonsomota

    View full-size slide

  92. Compose
    src/androidApp/build.gradle.kts
    :androidApp
    plugins {


    id("org.jetbrains.compose") version “1.0.0-beta5"


    id("com.android.application")


    kotlin("android")


    }


    View full-size slide

  93. Do I need to
    refactor The entire
    Project?

    View full-size slide

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

    View full-size slide

  95. 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

    View full-size slide

  96. What ‘challenges’
    will you find?

    View full-size slide

  97. 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

    View full-size slide

  98. 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

    View full-size slide

  99. 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

    View full-size slide

  100. 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

    View full-size slide

  101. How to Solve them

    View full-size slide

  102. 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

    View full-size slide

  103. Accompanist


    A set of libraries that provide Compose ready features


    Examples: Insets, Paging, Permissions, Swipe to refresh, etc.
    Compose: ‘Challenges’

    View full-size slide

  104. 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’

    View full-size slide

  105. 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! 🚀

    View full-size slide

  106. Accompanist (by Syer10)


    A subset of accompanist libraries ported by Syer10 to Desktop


    Available at: syer10.github.io/accompanist
    Compose: ‘Challenges’

    View full-size slide

  107. 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’

    View full-size slide

  108. 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? 😭

    View full-size slide

  109. 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’

    View full-size slide

  110. 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

    View full-size slide

  111. 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’

    View full-size slide

  112. 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’

    View full-size slide

  113. 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’

    View full-size slide

  114. 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’

    View full-size slide

  115. 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

    View full-size slide

  116. Compose: Image Loading
    Coil-Compose


    Image loading library implemented in Kotlin (and using Coroutines)
    @cafonsomota

    View full-size slide

  117. 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?

    View full-size slide

  118. 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! 🚀

    View full-size slide

  119. 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

    View full-size slide

  120. 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

    View full-size slide

  121. 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

    View full-size slide

  122. Compose: Resources
    Resources


    Imagine that you want to show an image
    @cafonsomota

    View full-size slide

  123. Compose: Resources
    Resources


    Imagine that you want to show an image
    Hello world!

    View full-size slide

  124. 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)


    )

    View full-size slide

  125. 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

    View full-size slide

  126. @Composable


    public expect fun icAbout(): Painter


    @Composable


    public expect fun icHome(): Painter
    Resources: Images
    shared-ui/commonMain/Icons.kt
    Compose: Resources

    View full-size slide

  127. @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

    View full-size slide

  128. @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

    View full-size slide

  129. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    @cafonsomota

    View full-size slide

  130. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    Hello world!
    Hello world!

    View full-size slide

  131. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    Hello world!
    Text(


    text = “Hello World!”,


    style = typography.h4


    )


    Hello world!

    View full-size slide

  132. 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!

    View full-size slide

  133. 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

    View full-size slide

  134. @Composable


    expect fun Font(


    name: String,


    res: String


    ): Font
    Resources: Font
    shared-ui/commonMain/platform/PlatformFont.kt
    Compose: Resources

    View full-size slide

  135. @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

    View full-size slide

  136. @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

    View full-size slide

  137. 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

    View full-size slide

  138. Compose: WebApp
    What about Web?
    @cafonsomota

    View full-size slide

  139. 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

    View full-size slide

  140. Compose: WebApp
    Div({


    style {


    position(Position.Relative)


    width(100.percent)


    height(400.px)


    flexGrow(1.0)


    marginBottom(10.px)


    }


    }) {


    Image(resource = image)


    }
    :webApp

    View full-size slide

  141. 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

    View full-size slide

  142. 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

    View full-size slide

  143. Getting everything together

    View full-size slide

  144. 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

    View full-size slide

  145. 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

    View full-size slide

  146. There’s one more thing?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  149. 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

    View full-size slide

  150. Photo by FarawayPictures on deviantART
    @cafonsomota
    IT JUST WORKS*


    (*RUNNING COMPOSE ON


    ANDROID, DESKTOP, AND THE WEB


    ALONG WITH KMP)

    View full-size slide