Sharing is Caring- Getting Started with Kotlin Multiplatform

Sharing is Caring- Getting Started with Kotlin Multiplatform

*** Presented in KotlinConf 2019, Droidcon Singapore 2019, Droidcon Vietnam 2019 ***

As Android developers, often we work with a backend service. Often in our team, there is an iOS project or a Javascript project, with similar functionality, that is being developed by our teammate developers next door. How fun would it be to write Kotlin code once and share it with all platforms? It will save us so much time and effort in implementation and testing! Please meet Kotlin Multiplatform! It is experimental, and yet very powerful and awesome.

This session will focus on creating a full-stack Kotlin project that fits an Android app and a backend Kotlin component. You’ll learn how to share code between the components to build more efficient and robust applications. And your teammate next door will thank you as well 🙂

3142db3adb711e247e371153b5777e04?s=128

Britt Barak

July 07, 2019
Tweet

Transcript

  1. 10.

    Drinks Emma`s GoodBye Balloons On A Call : Jurgo &

    Britt Jurgo: good? Jurgo: will go later Britt: red are the best! @brittBarak
  2. 15.
  3. 16.

    Emma`s GoodBye Conversation Drinks Drinks Balloons Balloons Red is best!

    Red is best! Will go tmrw Will go tmrw Call Call Prosecco! Prosecco! Is it good? Is it good? More prosecco! More prosecco!
  4. 17.

    Conversation Drinks Balloons Red is best! Will go tmrw Call

    Prosecco! Is it good? More prosecco! Balloons Cake Balloons Emma`s GoodBye Red is best! Will go tmrw Call Prosecco! Is it good? More prosecco! Drinks
  5. 43.

    Common kotlin/ JVM kotlin/ JS Target Kotlin Multiplatform Web browser

    Node.JS Android Backend Desktop @brittBarak
  6. 44.

    Common kotlin/ JVM kotlin/ JS kotlin/ Native Kotlin Multiplatform Web

    browser Node.JS Android Backend Desktop @brittBarak
  7. 45.

    Common kotlin/ JVM kotlin/ JS kotlin/ Native Kotlin Multiplatform Android

    Backend Desktop Web browser Node.JS iOS Android native Desktop native Web assembly @brittBarak
  8. 49.

    Supported platforms • jvm —> Kotlin/JVM • android —> Android

    applications and libraries • js —> Kotlin/JS • Kotlin/Native —> @brittBarak
  9. 50.

    Supported platforms (Native) •androidNativeArm32 , androidNativeArm64 —> Android NDK •iosArm32,

    iosArm64, iosX64 —> iOS •linuxArm32Hfp, linuxMips32, linuxMipsel32, linuxX64 —> Linux •macosX64 —> MacOS •mingwX64 —> Windows •wasm32 —> WebAssembly @brittBarak
  10. 53.

    build.gradle plugins {…} kotlin { jvm() js("nodeJs") { … }

    js(“browser") { … } } @brittBarak 2. Set targets
  11. 62.

    3. Source sets sourceSets { commonMain { dependencies { implementation

    ‘org.jetbrains.kotlin:kotlin-stdlib-common’ //… } } commonTest{…} } @brittBarak
  12. 63.

    sourceSets { commonMain {…} commonTest{…} androidMain { dependencies { implementation

    "androidx.lifecycle:lifecycle-extensions:2.0.0" implementation ‘com.nexmo.android:client-sdk:1.0.0' } } androidTest {..} 3. Source sets @brittBarak
  13. 64.

    sourceSets { commonMain {…} commonTest{…} androidMain { dependencies { implementation

    'androidx.lifecycle:lifecycle-extensions:2.0.0' implementation ‘com.nexmo.android:client-sdk:1.0.0' } } androidTest {..} 3. Source sets @brittBarak
  14. 68.

    app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event:

    NexmoEvent) { parseTextEvent(event.id, event.text, this@ListActivity) } @brittBarak
  15. 69.

    app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event:

    NexmoEvent) { parseTextEvent(event.id, event.text, this@ListActivity) } @brittBarak
  16. 70.

    app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event:

    NexmoEvent) { processCustomEvent(event, this@ListActivity) }
  17. 73.

    fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type)

    { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Drinks Balloon @brittBarak
  18. 74.

    fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type)

    { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Drinks Balloon @brittBarak
  19. 75.

    fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type)

    { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Balloon @brittBarak Drinks
  20. 76.

    fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type)

    { TYPE_ITEM_ADDED -> {} TYPE_TEXT -> { } } } commonMain Drinks Balloon “Hi!” @brittBarak
  21. 77.

    fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type)

    { TYPE_ITEM_ADDED -> {} TYPE_TEXT -> { … presenter.handleNewMessage (customEvent, position) } } } commonMain Drinks Balloon @brittBarak “Hi!”
  22. 79.

    override fun handleNewMessage(event: MyCustomEvent, position: Int) { val itemUiModel =

    uiModel.items[position] itemUiModel?.events?.addItem(EventUiModel(event)) rvItems.adapter?.notifyItemChanged(position) } • app @brittBarak
  23. 92.

    Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName)

    sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak
  24. 93.

    Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName)

    sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak
  25. 94.

    Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName)

    sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak
  26. 95.

    Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName)

    sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak
  27. 99.

    JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try

    { nexmoApiClient.post<String> { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak
  28. 100.

    JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try

    { nexmoApiClient.post<String> { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak
  29. 101.

    JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try

    { nexmoApiClient.post<String> { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak
  30. 103.
  31. 105.

    1. Same location 2. Same signature @brittBarak expect / actual

    expect fun sendCustomText(eventJson: String) actual fun sendCustomText(eventJson: String)
  32. 107.
  33. 108.
  34. 110.

    KotlinConf-19 sessions Today • Kotlin Multiplatform In Action/ Alexandr Pogrebnyak

    - 14:00, Aud15 • Bridge The Physical World: Kotlin/Native On Raspberry Pi/ Qian Jin - 14:00, Aud12 • Your Multiplatform Kaptain Has Arrived/ Ahmed El-Helw - 15:00 , Aud12 • Shipping A Mobile Multiplatform Project On Ios & Android/ Ben Asher, Alec Strong - 16:15 Keynote • Kotlin Native Concurrency Explained/ Kevin Galligan- 17:15 , Aud12 Tomorrow: • I Walk The Line: What Parts Of An App Should Be In Kotlin Native…/Ellen Shapiro - 10:15, Aud 15 • The State Of Kotlin/Js / Sebastian Aigner - 13:00, Aud 15 • Going Native/ Ana Redmond - 14:00, Aud15 • Effective Kotlin-Swift Interoperability / John Rodriguez- 16:15 , Aud11 Hands On Labs - Preparing Your Kotlin Multiplatform Development Environment/ Big Nerd Ranch - 16:15
  35. 111.

    Sum up •Share what you want, when you want. •Experimental

    •Prepare to explore •Popular (in a good way!) •Growing, evolving, improving