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

Challenges of Building Kotlin Multiplatform Libraries

Mohit S
March 25, 2022

Challenges of Building Kotlin Multiplatform Libraries

Mohit S

March 25, 2022
Tweet

More Decks by Mohit S

Other Decks in Programming

Transcript

  1. Mohit Sarveiya
    Building Kotlin Multiplatform Libraries
    @heyitsmohit

    View Slide

  2. Building Kotlin Multiplatform Libraries
    ● Setting up KMM project

    ● CI Challenges

    ● API Design Challenges

    View Slide

  3. Why Kotlin Multiplatform?
    Android

    Kotlin/JVM
    iOS

    Swift/LLVM
    Web

    JS

    View Slide

  4. Why Kotlin Multiplatform?
    API API API

    View Slide

  5. Why Kotlin Multiplatform?
    Retrofit Ajax Alamofire

    View Slide

  6. Why Kotlin Multiplatform?
    Room/SQL Delight Core Data

    View Slide

  7. Why Kotlin Multiplatform?
    Business Logic Business Logic Business Logic

    View Slide

  8. Why Kotlin Multiplatform?
    MVP/MVVM/MVI ReactJs VIPER

    View Slide

  9. Why Kotlin Multiplatform?
    Shared code

    View Slide

  10. Why Kotlin Multiplatform?
    API Business Logic Analytics
    Cache

    View Slide

  11. Setting up KMM Project

    View Slide

  12. Use Case
    Show platform name
    Hello

    Android

    View Slide

  13. Hello

    iOS
    Use Case
    9:41
    Show platform name

    View Slide

  14. Greeter
    Use Case

    View Slide

  15. How to create Multiplatform app

    View Slide

  16. Plugin
    https:
    //
    plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile

    View Slide

  17. Project Setup
    Shared

    View Slide

  18. Project Setup
    Shared
    Android App

    View Slide

  19. Project Setup
    Shared
    Android App iOS App
    XCode Project

    View Slide

  20. Project Setup
    Shared
    Android App iOS App

    View Slide

  21. Project Setup
    Shared
    Android App iOS App
    Framework

    View Slide

  22. Project Setup
    Shared
    Android App iOS App

    View Slide

  23. Shared Module Structure

    View Slide

  24. Shared Module
    Shared
    src
    commonMain

    View Slide

  25. Shared Module
    Shared
    src
    commonMain
    androidMain

    View Slide

  26. Shared Module
    Shared
    src
    commonMain
    androidMain
    iOSMain

    View Slide

  27. Greeter
    Use Case

    View Slide

  28. Common
    Shared Module
    Android iOS
    Platform name

    View Slide

  29. Common
    expect class Platform() {

    val platform: String

    }

    View Slide

  30. Common
    expect class Platform() {

    val platform: String

    }

    View Slide

  31. Common
    expect class Platform() {

    val platform: String

    }

    View Slide

  32. Common
    expect class Platform() {

    val platform: String

    }

    Common

    View Slide

  33. Common
    Android
    Android iOS
    Platform name

    View Slide

  34. Android
    actual class Platform actual constructor() {

    actual val platform: String = ”Android”

    }

    View Slide

  35. Android
    actual class Platform actual constructor() {

    actual val platform: String = ”Android”

    }

    View Slide

  36. Android
    actual class Platform actual constructor() {

    actual val platform: String = ”Android”

    }

    View Slide

  37. Android
    actual class Platform actual constructor() {

    actual val platform: String = ”Android”

    }

    Common
    Android

    View Slide

  38. Common
    iOS
    Android iOS
    Platform name

    View Slide

  39. iOS
    actual class Platform actual constructor() {

    actual val platform: String = “iOS”

    }

    View Slide

  40. Common
    Shared Module
    Android iOS
    Platform name

    View Slide

  41. Common
    class Greeter {

    fun greet(): String {

    return "Hello ${Platform().platform}!"

    }

    }

    View Slide

  42. Common
    class Greeter {

    fun greet(): String {

    return "Hello ${Platform().platform}!"

    }

    }

    View Slide

  43. Using Shared Module

    View Slide

  44. Project Setup
    Shared
    Android App iOS App

    View Slide

  45. Use Case
    Show platform name
    Hello

    Android

    View Slide

  46. Android App
    class MainActivity : AppCompatActivity() {

    }

    View Slide

  47. Android App
    class MainActivity : AppCompatActivity() {

    fun onCreate(
    ...
    ) {

    val greeting = Greeter().greet()



    }

    }

    View Slide

  48. Android App
    class MainActivity : AppCompatActivity() {

    fun onCreate(
    ...
    ) {

    val greeting = Greeter().greet()

    textView.text = greeting



    }

    }

    View Slide

  49. Android App
    class Greeter {

    ...


    }
    Common Source Build

    View Slide

  50. Use Case
    Hello

    Android

    View Slide

  51. Android App
    class MainActivity : AppCompatActivity() {

    fun onCreate(
    ...
    ) {

    val greeting = Greeter().greet()

    textView.text = greeting



    }

    }

    View Slide

  52. Hello

    iOS
    Use Case
    9:41
    Show platform name

    View Slide

  53. iOS App
    class Greeter {

    ...


    }
    Common Source Build Framework

    View Slide

  54. iOS App
    import SwiftUI

    import shared

    View Slide

  55. iOS App
    import SwiftUI

    import shared

    func greet()
    ->
    String {

    return Greeting().greeting()

    }

    View Slide

  56. iOS App
    import SwiftUI

    import shared

    struct ContentView: View {

    var body: some View {

    }

    }

    View Slide

  57. iOS App
    import SwiftUI

    import shared

    struct ContentView: View {

    var body: some View {

    Text(greet())

    }

    }

    View Slide

  58. Hello

    iOS
    Use Case
    9:41
    Show platform name

    View Slide

  59. Inside Objective-C Framework

    View Slide

  60. iOS Framework
    class Greeter {

    ...


    }
    Common Source Build Framework

    View Slide

  61. iOS Framework
    import SwiftUI

    import shared

    func greet()
    ->
    String {

    return Greeting().greeting()

    }

    View Slide

  62. iOS Framework
    Shared Base
    Shared Platform Shared Greeting

    View Slide

  63. Shared Base
    __attribute__((swift_name("KotlinBase")))


    @interface SharedBase : NSObject


    ...


    @end;


    View Slide

  64. Shared Base
    __attribute__((swift_name("KotlinBase")))


    @interface SharedBase : NSObject


    ...


    @end;


    View Slide

  65. iOS
    actual class Platform actual constructor() {

    actual val platform: String = “iOS”

    }

    View Slide

  66. Mappings
    https:
    //
    kotlinlang.org/docs/native-objc-interop.html#mappings

    View Slide

  67. Shared Platform
    __
    attribute
    __
    ((swift_name(“Platform")))

    @interface SharedPlatform : SharedBase

    ...


    @end;

    View Slide

  68. Shared Platform
    __
    attribute
    __
    ((swift_name(“Platform")))

    @interface SharedPlatform : SharedBase

    @property (readonly) NSString *platform

    @end;

    View Slide

  69. Common
    class Greeter {

    fun greet(): String {

    return "Hello ${Platform().platform}!"

    }

    }

    View Slide

  70. Common
    @interface SharedGreeting : SharedBase

    - (NSString *)greeting
    __
    attribute
    __
    ((swift_name("greeting()")));

    @end;

    View Slide

  71. Android & iOS Shared Modules

    View Slide

  72. Use Case
    Hello

    Android 29

    View Slide

  73. Shared Module
    Shared
    src
    commonMain
    androidMain
    iOSMain

    View Slide

  74. Android
    actual class Platform actual constructor() {

    actual val platform: String =

    “Android ${android.os.Build.VERSION.SDK_INT}"

    }

    View Slide

  75. Hello

    iOS 14.4
    Use Case
    9:41

    View Slide

  76. Shared Module
    Shared
    src
    commonMain
    androidMain
    iOSMain

    View Slide

  77. iOS
    import platform.UIKit.UIDevice

    actual class Platform actual constructor() {

    actual val platform: String =

    UIDevice.currentDevice.systemName() + " " +

    UIDevice.currentDevice.systemVersion

    }

    View Slide

  78. iOS
    import platform.UIKit.UIDevice

    actual class Platform actual constructor() {

    actual val platform: String =

    UIDevice.currentDevice.systemName() + " " +

    UIDevice.currentDevice.systemVersion

    }

    View Slide

  79. Summary
    ● How to build KMM project

    ● Shared Module Setup

    ● Inside Shared Framework

    View Slide

  80. CI Challenges

    View Slide

  81. Swift Package Manager

    View Slide

  82. Framework
    KMM Library

    View Slide

  83. Swift Package Manager
    KMM Library

    View Slide

  84. Multiplatform Swift Package
    ● Gradle plugin

    ● Generate XCFramework

    View Slide

  85. Multiplatform Swift Package
    id("com.chromaticnoise.multiplatform-swiftpackage") version "2.0.3"

    View Slide

  86. Multiplatform Swift Package
    multiplatformSwiftPackage {

    swiftToolsVersion(“5.5")

    targetPlatforms {

    iOS { v("13") }

    }

    }

    View Slide

  87. Multiplatform Swift Package
    ./gradlew createSwiftPackage

    View Slide

  88. KMM Library XCEFramework

    View Slide

  89. Projects/KMMProject
    Code ! Issues Pull Requests
    KMMLibrary.xcframework
    1 commit
    4c28f942 13 hours ago
    Package.swift
    KMMLibrary-1.0.zip
    README.md

    View Slide

  90. Choose Package Repository
    Search or enter package repository URL
    Name Last Updated Owner
    Projects(Github)
    KMMPackage Today 13:00 user

    View Slide

  91. Add Package to Project
    Choose package and targets
    Kind Add to Target
    KMMLibrary Library TestKMMLibrary
    Package Product

    View Slide

  92. Steps
    ● Create XCEFramework

    ● Consume using Swift Package Manager

    View Slide

  93. Build Automation

    View Slide

  94. KMM Library
    bdae142
    ..
    main
    50157a
    ..
    d89f145
    ..
    f0ddfb
    ..

    View Slide

  95. bdae142
    ..
    main
    50157a
    ..
    d89f145
    ..
    f0ddfb
    ..

    View Slide

  96. KMM Library
    Jar
    XCEFramework

    View Slide

  97. KMM Library
    Jar
    XCEFramework
    Artifactory

    View Slide

  98. Artifactory

    View Slide

  99. Build Automation
    ● Setup CI to create artifcats

    ● Use artifacts from repository like Artifactory

    View Slide

  100. API Design Challenges

    View Slide

  101. Flows

    View Slide

  102. Common
    fun getData(): Flow

    View Slide

  103. Android
    val flow = getData()

    flow.collect {



    }

    View Slide

  104. iOS
    getData(

    collector: T
    ##
    Kotlinx_coroutines_coreFlowCollector,

    completionHandler: (KotlinUnit?, Error?)
    ->
    Void

    )

    View Slide

  105. Common
    class CFlow internal constructor(

    val origin: Flow

    ) : Flow by origin {

    fun watch(block: (T)
    ->
    Unit) {

    }

    }

    View Slide

  106. Common
    class CFlow internal constructor(

    val origin: Flow

    ) : Flow by origin {

    fun watch(block: (T)
    ->
    Unit) {

    onEach { block(it) }

    launchIn(CoroutineScope(
    ...
    ))

    }

    }

    View Slide

  107. Common
    fun Flow.wrap(): CFlow = CFlow(this)

    View Slide

  108. iOS
    flow

    .wrap()

    .watch { data
    ->

    }

    View Slide

  109. Building Kotlin Multiplatform Libraries
    ● Setting up KMM project

    ● CI Challenges

    ● API Design Challenges

    View Slide

  110. Thank You!
    www.codingwithmohit.com
    @heyitsmohit

    View Slide