Slide 1

Slide 1 text

Copenhagen Denmark SHARING IS CARING INTRO TO KOTLIN MULTIPLATFORM BRITT BARAK NEXMO, VONAGE @brittBarak

Slide 2

Slide 2 text

Copenhagen Denmark SHARING IS CARING INTRO TO KOTLIN MULTIPLATFORM BRITT BARAK NEXMO, VONAGE

Slide 3

Slide 3 text

SHARING IS CARING

Slide 4

Slide 4 text

SHARING IS CARING

Slide 5

Slide 5 text

Drinks Gift Card Cake Balloons Emma`s GoodBye @brittBarak

Slide 6

Slide 6 text

Drinks Gift Card Cake Balloons Emma`s GoodBye @brittBarak

Slide 7

Slide 7 text

Drinks Emma`s GoodBye Balloons Britt: red are the best! Gift @brittBarak

Slide 8

Slide 8 text

Drinks Emma`s GoodBye Balloons Jurgo: will go later Gift Britt: red are the best! @brittBarak

Slide 9

Slide 9 text

Drinks Emma`s GoodBye Balloons Jurgo: good? Jurgo: will go later Britt: red are the best! @brittBarak

Slide 10

Slide 10 text

Drinks Emma`s GoodBye Balloons On A Call : Jurgo & Britt Jurgo: good? Jurgo: will go later Britt: red are the best! @brittBarak

Slide 11

Slide 11 text

Data Model Conversation

Slide 12

Slide 12 text

Conversation member member member member member member member member member member Data Model

Slide 13

Slide 13 text

Conversation member member member member member member member member member Data Model member

Slide 14

Slide 14 text

Data Model Conversation Event Event Event Event Event Event Event

Slide 15

Slide 15 text

Data Model Conversation Prosecco! Call Balloons Is it good? Drinks Will go tmrw Red is best! More prosecco!

Slide 16

Slide 16 text

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!

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Parse Sort Present OnNewEvent() @brittBarak

Slide 19

Slide 19 text

Parse Sort Present @brittBarak

Slide 20

Slide 20 text

Parse Sort Present @brittBarak

Slide 21

Slide 21 text

Parse Sort Present Present Present @brittBarak

Slide 22

Slide 22 text

Parse Sort Present Present Present Parse Sort Parse
 Sort @brittBarak

Slide 23

Slide 23 text

Parse Sort Present Present Present @brittBarak

Slide 24

Slide 24 text

@brittBarak Parse Sort Present Present Present Kotlin Multiplatform

Slide 25

Slide 25 text

@brittBarak Parse Sort Present Present Present Kotlin Multiplatform Share only what you want, when you want.

Slide 26

Slide 26 text

Parse Sort Present Present Present Kotlin Multiplatform @brittBarak

Slide 27

Slide 27 text

Common Present Present Present Kotlin Multiplatform @brittBarak

Slide 28

Slide 28 text

Common Target Target Target Kotlin Multiplatform @brittBarak

Slide 29

Slide 29 text

@brittBarak

Slide 30

Slide 30 text

@brittBarak JVM

Slide 31

Slide 31 text

@brittBarak JVM *.class

Slide 32

Slide 32 text

@brittBarak JVM *.class *.java MyClass.java

Slide 33

Slide 33 text

@brittBarak JVM *.class *.java javac MyClass.java MyClass.class

Slide 34

Slide 34 text

@brittBarak JVM *.class *.java *.kt javac

Slide 35

Slide 35 text

@brittBarak JVM *.class *.java *.kt javac MyFile.kt

Slide 36

Slide 36 text

@brittBarak JVM *.class *.java *.kt kotlinc javac MyFileKt.java MyFile.kt

Slide 37

Slide 37 text

@brittBarak JVM *.class *.java *.kt kotlinc javac MyFileKt.java MyFile.kt InnerClass.java

Slide 38

Slide 38 text

@brittBarak JVM *.class *.java *.kt kotlinc javac MyFileKt.java MyFile.kt InnerClass.java

Slide 39

Slide 39 text

@brittBarak JVM *.class *.java *.kt kotlinc javac MyFile.kt InnerClass.class MyFileKt.class

Slide 40

Slide 40 text

Common Target Target Target Kotlin Multiplatform @brittBarak

Slide 41

Slide 41 text

Common kotlin/ JVM Target Target Kotlin Multiplatform @brittBarak

Slide 42

Slide 42 text

Common kotlin/ JVM Target Target Kotlin Multiplatform Android Backend Desktop @brittBarak

Slide 43

Slide 43 text

Common kotlin/ JVM kotlin/ JS Target Kotlin Multiplatform Web browser Node.JS Android Backend Desktop @brittBarak

Slide 44

Slide 44 text

Common kotlin/ JVM kotlin/ JS kotlin/ Native Kotlin Multiplatform Web browser Node.JS Android Backend Desktop @brittBarak

Slide 45

Slide 45 text

Common kotlin/ JVM kotlin/ JS kotlin/ Native Kotlin Multiplatform Android Backend Desktop Web browser Node.JS iOS Android native Desktop native Web assembly @brittBarak

Slide 46

Slide 46 text

Get Started @brittBarak

Slide 47

Slide 47 text

1. Add plugin plugins { id("org.jetbrains.kotlin.multiplatform").version("1.3.61") } build.gradle @brittBarak

Slide 48

Slide 48 text

2. Set targets @brittBarak

Slide 49

Slide 49 text

Supported platforms • jvm —> Kotlin/JVM • android —> Android applications and libraries • js —> Kotlin/JS • Kotlin/Native —> @brittBarak

Slide 50

Slide 50 text

Supported platforms (Native) •androidNativeArm32 , androidNativeArm64 —> Android NDK •iosArm32, iosArm64, iosX64 —> iOS •linuxArm32Hfp, linuxMips32, linuxMipsel32, linuxX64 —> Linux •macosX64 —> MacOS •mingwX64 —> Windows •wasm32 —> WebAssembly @brittBarak

Slide 51

Slide 51 text

2. Set targets @brittBarak

Slide 52

Slide 52 text

build.gradle plugins {…} kotlin { jvm() js("nodeJs") { … } } @brittBarak 2. Set targets

Slide 53

Slide 53 text

build.gradle plugins {…} kotlin { jvm() js("nodeJs") { … } js(“browser") { … } } @brittBarak 2. Set targets

Slide 54

Slide 54 text

For Android @brittBarak

Slide 55

Slide 55 text

build.gradle kotlin { android() } @brittBarak

Slide 56

Slide 56 text

plugins { id("org.jetbrains.kotlin.multiplatform").version("1.3.61") id(“com.android.application") // or (“com.android.library") } kotlin { android() } @brittBarak

Slide 57

Slide 57 text

plugins { id("org.jetbrains.kotlin.multiplatform").version("1.3.61") id(“com.android.application") // or (“com.android.library”) } android { ... } kotlin { android() } @brittBarak

Slide 58

Slide 58 text

3. Source sets @brittBarak

Slide 59

Slide 59 text

3. Source sets sourceSets { common{} android{} jvm{} } @brittBarak

Slide 60

Slide 60 text

3. Source sets sourceSets { common{} android{} jvm{} } @brittBarak

Slide 61

Slide 61 text

3. Source sets sourceSets { commonMain{} commonTest{} androidMain{} androidTest{} } @brittBarak

Slide 62

Slide 62 text

3. Source sets sourceSets { commonMain { dependencies { implementation ‘org.jetbrains.kotlin:kotlin-stdlib-common’ //… } } commonTest{…} } @brittBarak

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

Project Structure /src commonMain commonTest androidMain androidTest iosMain iosTest

Slide 66

Slide 66 text

app—> common @brittBarak

Slide 67

Slide 67 text

common: Parse Sort app: Present on New Event() @brittBarak

Slide 68

Slide 68 text

app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event: NexmoEvent) { parseTextEvent(event.id, event.text, this@ListActivity) } @brittBarak

Slide 69

Slide 69 text

app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event: NexmoEvent) { parseTextEvent(event.id, event.text, this@ListActivity) } @brittBarak

Slide 70

Slide 70 text

app val eventListener: NexmoEventListener = object { override fun onCustomEvent(event: NexmoEvent) { processCustomEvent(event, this@ListActivity) }

Slide 71

Slide 71 text

fun processCustomEvent(event, presenter) { } commonMain Balloon @brittBarak

Slide 72

Slide 72 text

fun processCustomEvent(event, presenter) { val customEvent = Json.nonstrict. parse(MyCustomEvent.serializer(), event) } commonMain Drinks Balloon @brittBarak

Slide 73

Slide 73 text

fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type) { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Drinks Balloon @brittBarak

Slide 74

Slide 74 text

fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type) { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Drinks Balloon @brittBarak

Slide 75

Slide 75 text

fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type) { TYPE_ITEM_ADDED -> { presenter. handleItemAdded(customEvent) } } } commonMain Balloon @brittBarak Drinks

Slide 76

Slide 76 text

fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type) { TYPE_ITEM_ADDED -> {} TYPE_TEXT -> { } } } commonMain Drinks Balloon “Hi!” @brittBarak

Slide 77

Slide 77 text

fun processCustomEvent(event, presenter) { val customEvent = … when (customEvent.type) { TYPE_ITEM_ADDED -> {} TYPE_TEXT -> { … presenter.handleNewMessage (customEvent, position) } } } commonMain Drinks Balloon @brittBarak “Hi!”

Slide 78

Slide 78 text

interface EventsPresenter { fun handleItemAdded(event: MyCustomEvent) fun handleNewMessage(event: MyCustomEvent, position: Int) } • commonMain @brittBarak

Slide 79

Slide 79 text

override fun handleNewMessage(event: MyCustomEvent, position: Int) { val itemUiModel = uiModel.items[position] itemUiModel?.events?.addItem(EventUiModel(event)) rvItems.adapter?.notifyItemChanged(position) } • app @brittBarak

Slide 80

Slide 80 text

override fun handleNewMessage(event: MyCustomEvent, position: Int) { //… recyclerview.adapter.notifyItemChanged(position) } • app @brittBarak

Slide 81

Slide 81 text

Skipping Presenter? @brittBarak

Slide 82

Slide 82 text

common —> app @brittBarak

Slide 83

Slide 83 text

expect / actual @brittBarak

Slide 84

Slide 84 text

A word about architecture @brittBarak

Slide 85

Slide 85 text

Data Domain Presentation

Slide 86

Slide 86 text

Data Domain Presentation Platform Common expect/actual DataModel UseCase UiModel View Repository

Slide 87

Slide 87 text

AddItem @brittBarak

Slide 88

Slide 88 text

Android btnAdd.setOnClickListener { //… uiModel.conversationLiveData. value?.let { it -> AddItem().execute( tilItemName.editText?.text.toString()) } } @brittBarak

Slide 89

Slide 89 text

Android btnAdd.setOnClickListener { //… uiModel.conversationLiveData. value?.let { it -> AddItem().execute( tilItemName.editText?.text.toString()) } } @brittBarak

Slide 90

Slide 90 text

Android btnAdd.setOnClickListener { //… uiModel.conversationLiveData. value?.let { it -> AddItem().execute(itemName) } } @brittBarak

Slide 91

Slide 91 text

Common/ AddItem.kt @brittBarak

Slide 92

Slide 92 text

Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName) sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak

Slide 93

Slide 93 text

Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName) sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak

Slide 94

Slide 94 text

Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName) sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak

Slide 95

Slide 95 text

Common/ AddItem.kt fun execute(itemName: String) { val eventJson = createEventJson(itemName) sendCustomText(eventJson) } expect fun sendCustomText(eventJson: String) @brittBarak

Slide 96

Slide 96 text

android/ AddItem.kt actual fun sendCustomText(eventJson: String) { conversation?.sendText(eventJson, listener) } @brittBarak

Slide 97

Slide 97 text

android/ AddItem.kt actual fun sendCustomText(eventJson: String) { conversation?.sendText(eventJson, listener) } @brittBarak

Slide 98

Slide 98 text

ios/ AddItem.kt actual fun sendCustomText(eventJson: String) { activeConversation? .sendText(eventJson, completion: … //… } } @brittBarak

Slide 99

Slide 99 text

JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try { nexmoApiClient.post { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak

Slide 100

Slide 100 text

JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try { nexmoApiClient.post { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak

Slide 101

Slide 101 text

JVM/ AddItem.kt actual fun sendCustomText(eventJson: String) { coroutineScope.launch(ApplicationDispatcher) { try { nexmoApiClient.post { url(pathSendEvent) body = TextContent(eventJson, ContentType.Application.Json) } // … } } @brittBarak

Slide 102

Slide 102 text

expect / actual

Slide 103

Slide 103 text

1. Same location @brittBarak expect / actual Common/ AddItem.kt android/ AddItem.kt ios/ AddItem.kt js/ AddItem.kt

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

1. Same location 2. Same signature @brittBarak expect / actual expect fun sendCustomText(eventJson: String) actual fun sendCustomText(eventJson: String)

Slide 106

Slide 106 text

What can I use? @brittBarak

Slide 107

Slide 107 text

Packages

Slide 108

Slide 108 text

Packages

Slide 109

Slide 109 text

Libraries •KotlinX (serialsation) •Ktor (networking) •Coroutines (async) •SQKDelight (persistency) •more… • https://github.com/AAkira/Kotlin-Multiplatform-Libraries

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

Sum up •Share what you want, when you want. •Experimental •Prepare to explore •Popular (in a good way!) •Growing, evolving, improving

Slide 112

Slide 112 text

Keep Sharing and caring

Slide 113

Slide 113 text

Keep Sharing and caring Thank you! @BrittBarak Join the goodbye party:)

Slide 114

Slide 114 text

#KotlinConf THANK YOU AND REMEMBER TO VOTE Britt Barak @brittBarak