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

An Android, a Desktop, and a Web developer enter in a bar

cmota
October 07, 2021

An Android, a Desktop, and a Web developer enter in a bar

Three different platforms meet at a bar and decided to share (pun intended) a couple of drinks.

This last year has been great for multiplatform development. As Kotlin keeps pushing for new releases and KMP starts to gain more adoption and stable releases, we now have the chance to write the UI for our Android apps with Compose and share it along with the Desktop and the Web.

In this talk, you’re going to see how you can start to decompose your Android app and start sharing all of its content along with a Desktop app and the Web. Drink at your own responsibility.

cmota

October 07, 2021
Tweet

More Decks by cmota

Other Decks in Technology

Transcript

  1. @cafonsomota
    An Android, A Desktop,
    and A Web Developer


    enter in a Bar
    Photo by Alexander Popov on Unsplash

    View full-size slide

  2. Photo by Alexander Popov on Unsplash
    An Android, A Desktop,
    and A Web Developer


    enter in a Bar
    *following all the public health measures
    @cafonsomota

    View full-size slide

  3. hello mobiconf! 👋
    @cafonsomota

    View full-size slide

  4. 👨💻 Android GDE


    🗣 Founder @GDGCoimbra and co-founder @Kotlin_Knights


    ✍ Author @rwenderlich


    🗺 Loves travel, photography and running


    🍻 Looking to taste a Zywiec Biale with all of you
    hello mobiconf! 👋
    @cafonsomota

    View full-size slide

  5. 🖥 Slides


    speakerdeck.com/cmota/an-android-a-desktop-and-a-web-developer-enter-in-a-bar


    👉 Code


    github.com/cmota/alicerce


    github.com/cmota/unsplash


    🍿 YouTube


    bit.ly/cmota-youtube
    Materials
    @cafonsomota

    View full-size slide

  6. 💬 How we built a Jetpack Compose Chat SDK, by Filip Babić


    📱 KMP for Mobile Developers, by Enrique López Mañas


    Mobiconf talks
    @cafonsomota

    View full-size slide

  7. A Brief history of Time

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  11. myths of


    native, hybrid, and cross
    platform solutions

    View full-size slide

  12. @cafonsomota
    droiders 🤖

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. @cafonsomota
    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

    View full-size slide

  16. @cafonsomota
    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!

    View full-size slide

  17. @cafonsomota
    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!

    View full-size slide

  18. @cafonsomota
    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!

    View full-size slide

  19. @cafonsomota
    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

    View full-size slide

  20. How to develop an
    application?

    View full-size slide

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

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

  23. How to develop an
    application?
    Spoilers

    View full-size slide

  24. How to develop an
    application?

    View full-size slide

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

  26. Kotlin Multiplatform

    View full-size slide

  27. @cafonsomota
    Kotlin Multiplatform
    shares your business logic

    View full-size slide

  28. presentation
    model
    parser
    view
    network
    presentation
    model
    parser
    view
    network
    presentation
    model
    parser
    view
    network
    presentation
    model
    parser
    view
    network
    desktop
    web
    iOS
    android
    @cafonsomota

    View full-size slide

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

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

  31. Kotlin Multiplatform: Platform Specific Code
    src/commonMain/sample/Platform.kt
    :shared
    @cafonsomota
    expect object Platform {


    val name: String


    }


    View full-size slide

  32. src/commonMain/sample/Platform.kt
    :shared
    @cafonsomota
    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

    View full-size slide

  33. src/commonMain/sample/Platform.kt
    :shared
    @cafonsomota
    expect object Platform {


    val name: String


    }


    src/androidMain/sample/Platform.kt
    actual object Platform {


    actual val name: String = "android"


    }


    Kotlin Multiplatform: Platform Specific Code

    View full-size slide

  34. src/commonMain/sample/Platform.kt
    :shared
    @cafonsomota
    expect object Platform {


    val name: String


    }


    src/androidMain/sample/Platform.kt
    actual object Platform {


    actual val name: String = “android”


    }


    Kotlin Multiplatform: Platform Specific Code

    View full-size slide

  35. src/commonMain/sample/Platform.kt
    :shared
    @cafonsomota
    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

    View full-size slide

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

    View full-size slide

  37. How to develop an
    application?

    View full-size slide

  38. developer.android.com/jetpack/compose

    View full-size slide

  39. Jetpack Compose
    compose.animation


    compose.material


    compose.foundation


    compose.ui


    compose.runtime


    compose.compiler


    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

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

  46. blog.jetbrains.com/kotlin/2021/08/compose-multiplatform-goes-alpha/

    View full-size slide

  47. Android, desktop, and Web

    View full-size slide

  48. @cafonsomota
    :androidApp

    View full-size slide

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

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  56. KOtlin Multiplatform: Targets
    @cafonsomota
    jvm
    JS


    android
    android

    NDK
    iOS
    watchOS
    tvOS
    macOS
    Linux
    Windows
    Web


    Assembly

    View full-size slide

  57. KOtlin Multiplatform: Libraries
    @cafonsomota
    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


    View full-size slide

  58. How to Start?

    View full-size slide

  59. @cafonsomota
    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

    View full-size slide

  60. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View full-size slide

  61. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View full-size slide

  62. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View full-size slide

  63. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared

    View full-size slide

  64. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared

    View full-size slide

  65. androidApp/


    desktopApp/


    webApp/


    shared/
    @cafonsomota
    KOtlin Multiplatform: Project Structure
    :shared
    androidMain/


    commonMain/


    iosMain/

    View full-size slide

  66. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/
    :shared

    View full-size slide

  67. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/

    View full-size slide

  68. KOtlin Multiplatform: Adding new Targets
    kotlin {a


    android()


    iOS()1


    }b


    shared/build.gradle.kts
    :shared

    View full-size slide

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

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

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

  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

    View full-size slide

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

  74. Do I need to
    refactor The entire
    Project?

    View full-size slide

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

    View full-size slide

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

  77. @cafonsomota
    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?

    View full-size slide

  78. What ‘challenges’
    will you find?

    View full-size slide

  79. KOtlin Multiplatform: ‘Challenges’
    @cafonsomota
    🟡 Not all libraries are available on KMP


    Those who are might not support all targets


    They might not be compatible with your Kotlin version


    View full-size slide

  80. KOtlin Multiplatform: ‘Challenges’
    @cafonsomota
    🟡 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

    View full-size slide

  81. KOtlin Multiplatform: ‘Challenges’
    @cafonsomota
    🟡 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

    View full-size slide

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

    View full-size slide

  83. How to Start?

    View full-size slide

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


    View full-size slide

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


    View full-size slide

  86. @cafonsomota
    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 🙂

    View full-size slide

  87. @cafonsomota
    Compose: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    Unsplash

    View full-size slide

  88. @cafonsomota
    androidApp/


    desktopApp/


    webApp/


    shared/


    shared-ui/
    :shared-ui
    Compose: Project Structure

    View full-size slide

  89. @cafonsomota
    androidApp/


    desktopApp/


    webApp/


    shared/


    shared-ui/
    :shared-ui
    androidMain/


    commonMain/


    desktopMain/
    Compose: Project Structure

    View full-size slide

  90. @cafonsomota
    Compose
    Compose for Android


    androidx.compose


    View full-size slide

  91. @cafonsomota
    Compose
    Compose for Android


    androidx.compose


    Compose for Desktop/Web


    org.jetbrains.compose


    View full-size slide

  92. Compose
    src/shared-ui/build.gradle.kts
    :shared-ui
    plugins {


    kotlin("multiplatform")


    id("org.jetbrains.compose") version "1.0.0-alpha3"


    id("com.android.library")


    kotlin("plugin.serialization")


    }


    View full-size slide

  93. Compose
    src/shared-ui/build.gradle.kts
    :shared-ui
    plugins {


    kotlin("multiplatform")


    id("org.jetbrains.compose") version "1.0.0-alpha3"


    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

  94. @cafonsomota
    Compose
    💥 Duplicated class androidx.compose.*


    ...

    BUILD FAILED


    View full-size slide

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


    androidx.compose


    org.jetbrains.compose


    View full-size slide

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


    id("org.jetbrains.compose") version "1.0.0-alpha3"


    id("com.android.application")


    kotlin("android")


    }


    View full-size slide

  97. Do I need to
    refactor The entire
    Project?

    View full-size slide

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

    View full-size 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

    View full-size slide

  100. What ‘challenges’
    will you find?

    View full-size slide

  101. Compose: ‘Challenges’
    @cafonsomota
    🟠 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


    View full-size slide

  102. Compose: ‘Challenges’
    @cafonsomota
    🟠 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

    View full-size slide

  103. Compose: ‘Challenges’
    @cafonsomota
    🟠 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


    View full-size slide

  104. Compose: ‘Challenges’
    @cafonsomota
    🔴 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


    View full-size slide

  105. How to Solve them

    View full-size slide

  106. Compose: ‘Challenges’
    @cafonsomota
    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

    View full-size slide

  107. Accompanist


    A set of libraries that provide Compose ready features


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

    View full-size 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 full-size 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 full-size slide

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

  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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

  120. Compose: Image Loading
    Coil-Compose


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

    View full-size 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 full-size 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 full-size 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 full-size 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 full-size 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 full-size slide

  126. 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
    ⚠ Last supported version is 1.0.0-alpha3 (Kamel version 0.2.2)

    View full-size slide

  127. Compose: Resources
    Resources


    Imagine that you want to show an image
    @cafonsomota

    View full-size slide

  128. Compose: Resources
    Resources


    Imagine that you want to show an image
    Hello world!

    View full-size slide

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

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

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

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

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

  134. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    @cafonsomota

    View full-size slide

  135. Compose: Resources
    Resources


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

    View full-size slide

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

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

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

  139. @Composable


    expect fun Font(


    name: String,


    res: String


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

    View full-size slide

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

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

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

  143. Compose: WebApp
    What about Web?
    @cafonsomota

    View full-size slide

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

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

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

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

  148. Getting everything together

    View full-size slide

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

  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

    View full-size slide

  151. There’s one more thing?

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  154. Kotlin Multiplatform and Compose template
    Alicerce


    In Portuguese alicerce means foundation


    A Kotlin Multiplatform with Compose template


    Currently supports: Android, Desktop and Web


    Contains an initial project con
    fi
    guration along with the libraries mentioned here


    Open to feedback and contributions!
    Alicerce

    View full-size slide

  155. Photo by Hans Isaacson on Unsplash
    @cafonsomota
    An Android, A Desktop,
    and A Web Developer


    enter in a Bar

    View full-size slide