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

  3. hello mobiconf! 👋
    @cafonsomota

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

  7. A Brief history of Time

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. myths of


    native, hybrid, and cross
    platform solutions

    View Slide

  12. @cafonsomota
    droiders 🤖

    View Slide

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

    View Slide

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

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

  20. How to develop an
    application?

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

  23. How to develop an
    application?
    Spoilers

    View Slide

  24. How to develop an
    application?

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

  26. Kotlin Multiplatform

    View Slide

  27. @cafonsomota
    Kotlin Multiplatform
    shares your business logic

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

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


    val name: String


    }


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

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

    View Slide

  37. How to develop an
    application?

    View Slide

  38. Compose

    View Slide

  39. developer.android.com/jetpack/compose

    View Slide

  40. Compose

    View Slide

  41. 🤔
    Compose

    View Slide

  42. Jetpack Compose
    compose.animation


    compose.material


    compose.foundation


    compose.ui


    compose.runtime


    compose.compiler


    View Slide

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

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

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

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

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

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

    View Slide

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

    View Slide

  50. Android, desktop, and Web

    View Slide

  51. @cafonsomota
    :androidApp

    View Slide

  52. :desktopApp

    View Slide

  53. :webApp

    View Slide

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

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  61. KOtlin Multiplatform: Targets
    @cafonsomota
    jvm
    JS


    android
    android

    NDK
    iOS
    watchOS
    tvOS
    macOS
    Linux
    Windows
    Web


    Assembly

    View Slide

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

  63. How to Start?

    View Slide

  64. @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 Slide

  65. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View Slide

  66. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View Slide

  67. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    iosApp/


    shared/
    :shared

    View Slide

  68. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared

    View Slide

  69. @cafonsomota
    KOtlin Multiplatform: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    :shared

    View Slide

  70. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    iosMain/

    View Slide

  71. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/
    :shared

    View Slide

  72. androidApp/


    desktopApp/


    webApp/


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


    commonMain/


    desktopMain/


    jsMain/

    View Slide

  73. KOtlin Multiplatform: Adding new Targets
    kotlin {a


    android()


    iOS()1


    }b


    shared/build.gradle.kts
    :shared

    View Slide

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

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

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

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

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

  79. Do I need to
    refactor The entire
    Project?

    View Slide

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

    View Slide

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

  82. @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 Slide

  83. What ‘challenges’
    will you find?

    View Slide

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

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

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

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

    View Slide

  88. How to Start?

    View Slide

  89. @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 Slide

  90. @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 Slide

  91. @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 Slide

  92. @cafonsomota
    Compose: Project Structure
    androidApp/


    desktopApp/


    webApp/


    shared/
    Unsplash

    View Slide

  93. @cafonsomota
    androidApp/


    desktopApp/


    webApp/


    shared/


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

    View Slide

  94. @cafonsomota
    androidApp/


    desktopApp/


    webApp/


    shared/


    shared-ui/
    :shared-ui
    androidMain/


    commonMain/


    desktopMain/
    Compose: Project Structure

    View Slide

  95. @cafonsomota
    Compose
    Compose for Android


    androidx.compose


    View Slide

  96. @cafonsomota
    Compose
    Compose for Android


    androidx.compose


    Compose for Desktop/Web


    org.jetbrains.compose


    View Slide

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

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

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


    ...

    BUILD FAILED


    View Slide

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


    androidx.compose


    org.jetbrains.compose


    View Slide

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


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


    id("com.android.application")


    kotlin("android")


    }


    View Slide

  102. Do I need to
    refactor The entire
    Project?

    View Slide

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

    View Slide

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

  105. What ‘challenges’
    will you find?

    View Slide

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

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

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

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

  110. How to Solve them

    View Slide

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

  112. Accompanist


    A set of libraries that provide Compose ready features


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

    View Slide

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

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

  115. Accompanist (by Syer10)


    A subset of accompanist libraries ported by Syer10 to Desktop


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

    View Slide

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

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

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

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

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

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

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

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

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

  125. Compose: Image Loading
    Coil-Compose


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

    View Slide

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

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

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

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

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

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

  132. Compose: Resources
    Resources


    Imagine that you want to show an image
    @cafonsomota

    View Slide

  133. Compose: Resources
    Resources


    Imagine that you want to show an image
    Hello world!

    View Slide

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

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

  136. @Composable


    public expect fun icAbout(): Painter


    @Composable


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

    View Slide

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

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

  139. Compose: Resources
    Resources


    Imagine that you want to set a custom font
    @cafonsomota

    View Slide

  140. Compose: Resources
    Resources


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

    View Slide

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

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

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

  144. @Composable


    expect fun Font(


    name: String,


    res: String


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

    View Slide

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

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

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

  148. Compose: WebApp
    What about Web?
    @cafonsomota

    View Slide

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

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

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

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

  153. Getting everything together

    View Slide

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

  155. Resources

    View Slide

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

  157. There’s one more thing?

    View Slide

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

    View Slide

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

    View Slide

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

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


    enter in a Bar

    View Slide