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 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 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 Slide

  4. A Brief history of Time

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  8. myths of


    native, hybrid, and cross
    platform solutions

    View Slide

  9. droiders 🤖
    @cafonsomota

    View Slide

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

    View Slide

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

    View 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 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 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 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 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 Slide

  17. How to develop an
    application?

    View 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 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 Slide

  20. How to develop an
    application?
    Spoilers

    View Slide

  21. How to develop
    an application?

    View 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 Slide

  23. Kotlin Multiplatform

    View Slide

  24. Kotlin Multiplatform
    shares your business logic
    @cafonsomota

    View 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 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 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 Slide

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


    val name: String


    }


    :shared
    @cafonsomota

    View 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 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 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 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 Slide

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

    View Slide

  34. How to develop
    an application?

    View Slide

  35. Compose

    View Slide

  36. developer.android.com/jetpack/compose

    View Slide

  37. Compose

    View Slide

  38. 🤔
    Compose

    View Slide

  39. Jetpack Compose
    compose.animation


    compose.material


    compose.foundation


    compose.ui


    compose.runtime


    compose.compiler


    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

  47. Android, desktop, and Web

    View Slide

  48. @cafonsomota
    :androidApp

    View Slide

  49. :androidWearApp

    View Slide

  50. @cafonsomota
    :desktopApp

    View Slide

  51. :webApp

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  59. KOtlin Multiplatform: Targets
    jvm
    JS


    android
    android

    NDK
    iOS
    watchOS
    tvOS
    macOS
    Linux
    Windows
    Web


    Assembly
    @cafonsomota

    View Slide

  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

    View Slide

  61. How to Start?

    View Slide

  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

    View Slide

  63. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View Slide

  64. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View Slide

  65. KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared
    @cafonsomota

    View Slide

  66. KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared
    @cafonsomota

    View Slide

  67. KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared
    @cafonsomota

    View Slide

  68. androidApp/


    desktopApp/


    webApp/


    shared/
    KOtlin Multiplatform: Project Structure
    androidMain/


    commonMain/


    iosMain/
    :shared
    @cafonsomota

    View Slide

  69. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/
    :shared
    @cafonsomota

    View Slide

  70. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/
    @cafonsomota

    View Slide

  71. KOtlin Multiplatform: Adding new Targets
    kotlin {a


    android()


    iOS()1


    }b


    shared/build.gradle.kts
    :shared

    View Slide

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


    android()


    jvm("desktop")


    js(IR) {c


    browser()


    binaries.executable()


    }d


    }b
    :shared

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  77. Do I need to
    refactor The entire
    Project?

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  81. What ‘challenges’
    will you find?

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  86. How to Start?

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  90. Compose
    Compose for Android


    androidx.compose


    @cafonsomota

    View Slide

  91. Compose
    Compose for Android


    androidx.compose


    Compose for Desktop/Web


    org.jetbrains.compose


    @cafonsomota

    View Slide

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


    }


    View Slide

  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)


    }


    }


    }


    }


    View Slide

  94. Compose
    💥 Duplicated class androidx.compose.*


    ...

    BUILD FAILED


    @cafonsomota

    View Slide

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


    androidx.compose


    org.jetbrains.compose


    @cafonsomota

    View Slide

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


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


    id("com.android.application")


    kotlin("android")


    }


    View Slide

  97. Do I need to
    refactor The entire
    Project?

    View Slide

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

    View Slide

  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

    View Slide

  100. What ‘challenges’
    will you find?

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  105. How to Solve them

    View Slide

  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

    View Slide

  107. Accompanist


    A set of libraries that provide Compose ready features


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

    View Slide

  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’

    View Slide

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

    View Slide

  110. Accompanist (by Syer10)


    A subset of accompanist libraries ported by Syer10 to Desktop


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

    View Slide

  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’

    View Slide

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

    View Slide

  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’

    View Slide

  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

    View Slide

  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’

    View Slide

  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’

    View Slide

  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’

    View Slide

  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’

    View Slide

  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

    View Slide

  120. Compose: Image Loading
    Coil-Compose


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

    View Slide

  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?

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  126. Compose: Resources
    Resources


    Imagine that you want to show an image
    @cafonsomota

    View Slide

  127. Compose: Resources
    Resources


    Imagine that you want to show an image
    Hello world!

    View Slide

  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)


    )

    View Slide

  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

    View Slide

  130. @Composable


    public expect fun icAbout(): Painter


    @Composable


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

    View Slide

  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

    View Slide

  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

    View Slide

  133. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    @cafonsomota

    View Slide

  134. Compose: Resources
    Resources


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

    View Slide

  135. Compose: Resources
    Resources


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


    text = “Hello World!”,


    style = typography.h4


    )


    Hello world!

    View Slide

  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!

    View Slide

  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

    View Slide

  138. @Composable


    expect fun Font(


    name: String,


    res: String


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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  142. Compose: WebApp
    What about Web?
    @cafonsomota

    View Slide

  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

    View Slide

  144. Compose: WebApp
    Div({


    style {


    position(Position.Relative)


    width(100.percent)


    height(400.px)


    flexGrow(1.0)


    marginBottom(10.px)


    }


    }) {


    Image(resource = image)


    }
    :webApp

    View Slide

  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

    View Slide

  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

    View Slide

  147. Getting everything together

    View Slide

  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

    View Slide

  149. Resources

    View Slide

  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

    View Slide

  151. There’s one more thing?

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

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


    (*RUNNING COMPOSE ON


    ANDROID, DESKTOP, AND THE WEB


    ALONG WITH KMP)

    View Slide