Slide 1

Slide 1 text

Kotlin Multiplatform

Slide 2

Slide 2 text

The Hitchhikers Guide Through Kotlin Multiplatform The Hitchhikers Guide Through Kotlin Multiplatform @cafonsomota

Slide 3

Slide 3 text

speakerdeck.com/cmota/ the-hitchhikers-guide-through-kotlin-multiplatform @cafonsomota

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

a brief history of time “In the beginning the Universe was created. This had made many people angry and has been widely regarded as a bad move.”

Slide 6

Slide 6 text

android iOS

Slide 7

Slide 7 text

Dark Theme

Slide 8

Slide 8 text

android iOS

Slide 9

Slide 9 text

Photo by Fabian Grohs on Unsplash

Slide 10

Slide 10 text

Photo by Fabian Grohs on Unsplash a wild application idea appears! develop it for Android and iOS.

Slide 11

Slide 11 text

-hire a team of specialised developers -define requirements -plan features development -start development/ write unit tests -write t-specs for SQA validation -cross-checking validation between both platforms (or jacks) Steps

Slide 12

Slide 12 text

~2xthe team the cost the status meetings required the time spent on development the time spent on testing native the time spent on bug fixing

Slide 13

Slide 13 text

Photo by Fabian Grohs on Unsplash a wild application idea appears! develop it for Android and iOS and web.

Slide 14

Slide 14 text

~3xthe team the cost the status meetings required the time spent on development the time spent on testing the time spent on bug fixing

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

let’s find a solution that works on all platforms.

Slide 17

Slide 17 text

2008 2012 2018 2013 2011 2017 2006 2010 2009 2015 * Kotlin Multiplatform *

Slide 18

Slide 18 text

- smaller team - typically half of the cost needed on native - small learning curve for web developers (advantages) Cross-platform

Slide 19

Slide 19 text

- chained to the framework implementation of UI - new updates from the OS will take time to adopt - performance is not the same - some native code might need to be written - OS/ device features are dependent on the fw support - dart is not widely used language (for now) (disadvantages) Cross-platform

Slide 20

Slide 20 text

how can we have the best of both worlds?

Slide 21

Slide 21 text

how can we have the best of both worlds?

Slide 22

Slide 22 text

kotlin “42.”

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

- developed by JetBrains - open source - concise, safe, interoperable, tool-friendly - supported/ used by Google for Android Development - it’s more than “just for Android” Kotlin Server-side Android Kotlin JS Native

Slide 25

Slide 25 text

Mutability etc. Null safety Default values Type inference String interpolation when Collections

Slide 26

Slide 26 text

NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException TransactionTooLargeException

Slide 27

Slide 27 text

public class Conference { private String mName; private String mLocal; private List mTechs; public Conference(String name, String local, List techs) { mName = name; mLocal = local; mTechs = techs; } public String getName() { return mName; } public void setName(String name) { Conference.java (less code) Concise

Slide 28

Slide 28 text

data class Conference (val name: String, val location: String, val techs: List) (less code) Concise Conference.kt

Slide 29

Slide 29 text

Less bugs! more free time (and happier team… and management) (less code) Concise

Slide 30

Slide 30 text

-getOrElse() -find() -filter() -filterNot() -filterNotNull() -flatMap() -mapNotNull() -all() -any() -sumBy() -zip() -… -take() -takeLast() -sortBy() -sortByDescending() -groupBy() -map() (collections) Language features

Slide 31

Slide 31 text

mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7, 8, 9)
 
 
 > [1, null, 2, null, 3, 4, 5, 6, 7, 8, 9] (collections) Language features output

Slide 32

Slide 32 text

> [1, 2, 3, 4, 5, 6, 7, 8, 9] (collections) Language features output mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7, 8, 9)
 .filterNotNull()
 


Slide 33

Slide 33 text

> [2, 4, 6, 8] mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7, 8, 9)
 .filterNotNull()
 .filter { it % 2 == 0 }
 (collections) Language features output

Slide 34

Slide 34 text

> [8, 6, 4, 2] mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7, 8, 9)
 .filterNotNull()
 .filter { it % 2 == 0 }
 .sortedDescending() (collections) Language features output

Slide 35

Slide 35 text

- small learning curve involved - easily to go from JavaScript/ Swift into Kotlin and back (from a developers’ point of view) Easy to learn

Slide 36

Slide 36 text

var variable = 42 variable = 1 let value = 42 var variable = 42 variable = 1 val value = 42 *adapted from http://nilhcem.com/swift-is-like-kotlin/ (variables and constants) Kotlin vs Swift Kotlin Swift

Slide 37

Slide 37 text

fun greet(name: String, day: String): String { return "Hello $name, today is $day." } greet(“Porto", “Saturday") *updated from http://nilhcem.com/swift-is-like-kotlin/ func greet(_ name: String,_ day: String) -> String { return "Hello \(name), today is \(day)." } greet(“Porto", “Saturday") Kotlin Swift (functions) Kotlin vs Swift

Slide 38

Slide 38 text

kotlin multiplatform “‘Resistance is useless!’ How can anyone maintain a positive mental attitude if you’re saying things like that?”

Slide 39

Slide 39 text

K otlin multiplatform using kotlin in projects that target more than one platform

Slide 40

Slide 40 text

(advantages) - language features - kotlin first! - low risk - you decide what’s worth to share across projects - interoperability - consistency across platforms - strong community support Kotlin Multiplatform

Slide 41

Slide 41 text

first reaction

Slide 42

Slide 42 text

view view view view model parser network presentation presentation presentation presentation network network network parser parser parser model model model presentation presentation presentation desktop web iOS android

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

android iOS web desktop model parser network presentation common view view view view java/kotlin objective-c/ swift (kotlin) JS supported in jvm

Slide 45

Slide 45 text

but how can they expect to communicate?

Slide 46

Slide 46 text

declared at common module expect declared at android module actual declared at iOS module declared at …

Slide 47

Slide 47 text

we want a platform-specific value for name

Slide 48

Slide 48 text

expect object Platform { val name: String } commonMain src/commonMain/sample/Platform.kt

Slide 49

Slide 49 text

commonMain src/commonMain/sample/Platform.kt - define actual on android - define actual on iOS targets: android and iOS expect object Platform { val name: String }

Slide 50

Slide 50 text

src/iOSMain/sample/Platform.kt actual object Platform { actual val name: String = "Android" } actual object Platform { actual val name: String = "iOS" } src/androidMain/sample/Platform.kt platform-dependent code

Slide 51

Slide 51 text

IntelliJ will ask you declare the implementations for actual

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

medium.com/@cafonsomota

Slide 54

Slide 54 text

demo "For a moment, nothing happened. Then, after a second or so, nothing continued to happen.”

Slide 55

Slide 55 text

github.com/cmota/commit19

Slide 56

Slide 56 text

- implement UI - RecyclerView (Android)/ UITableViewController (iOS) - make network request - parse response object - notify the UI - that there’s new content available to be draw - reload the list project structure

Slide 57

Slide 57 text

android iOS Retrofit Alamofire GSON/ Moshi JSONSerialization MVP, MVVM, MVI MVVM, ELM RxJava RxSwift Tests Tests Activity UIViewController RecyclerView UITableView

Slide 58

Slide 58 text

Retrofit Alamofire GSON/ Moshi JSONSerialization MVP, MVVM, MVI MVVM, ELM RxJava RxSwift Tests Tests Activity UIViewController RecyclerView UITableView android iOS

Slide 59

Slide 59 text

Retrofit Alamofire GSON/ Moshi JSONSerialization MVP, MVVM, MVI MVVM, ELM RxJava RxSwift Tests Tests android iOS Activity UIViewController RecyclerView UITableView unnecessary duplication

Slide 60

Slide 60 text

class CommitAPI(engine: HttpClientEngine) { private val client = HttpClient(engine) { install(JsonFeature) { serializer = KotlinxSerializer() } } suspend fun fetchSpeakers(): AllSpeakersEntity { val response = client.get{ url ("$URL")} val json = response.readText() return Json.parse(SpeakersEntity.serializer(), json) } } network src/commonMain/data/CommitAPI.kt android business logic model parser network presentation view

Slide 61

Slide 61 text

class CommitAPI(engine: HttpClientEngine) { private val client = HttpClient(engine) { install(JsonFeature) { serializer = KotlinxSerializer() } } suspend fun fetchSpeakers(): AllSpeakersEntity { val response = client.get{ url ("$URL")} val json = response.readText() return Json.parse(SpeakersEntity.serializer(), json) } } parser src/commonMain/data/CommitAPI.kt android business logic model parser network presentation view

Slide 62

Slide 62 text

{ “speaker": "Carlos Mota", "company": "WIT SOFTWARE", "title": "Lead Software Engineer", "bio": “... GDG Coimbra organizer and Kotlin evangelist, he also has a huge passion for travel, photography, space and the occasional run.", "talk_title": "The Hitchhikers Guide Through Kotlin Multiplatform", “talk_description”:”... But what I told that you could just develop in Kotlin and run it seamlessly on all devices? Here comes Kotlin Multiplatform!", "talk_time":"16:00", "img": “https://commitporto.com/static/speakers/carlos.jpg" ... } json response http://gist.github.com/cmota/…commit-speakers.json

Slide 63

Slide 63 text

{ "speaker": "Carlos Mota", "company": "WIT SOFTWARE", "title": "Lead Software Engineer", "bio": "... GDG Coimbra organizer and Kotlin evangelist, he also has a huge passion for travel, photography, space and the occasional run.", "talk_title": "The Hitchhikers Guide Through Kotlin Multiplatform", "talk_description”:"... But what I told that you could just develop in Kotlin and run it seamlessly on all devices? Here comes Kotlin Multiplatform!", "talk_time":"16:00", "img": "https://commitporto.com/static/speakers/carlos.jpg" ... } json response http://gist.github.com/cmota/…commit-speakers.json

Slide 64

Slide 64 text

@Serializable data class Speaker(val speaker: String, val company: String, val title: String, val bio: String, @SerialName("talk_title") val title: String, @SerialName("talk_description") val description: String, @SerialName("talk_time") val schedule: String, val img: String) model src/commonMain/data/Speaker.kt ktor-client-serialization android business logic model parser network presentation view

Slide 65

Slide 65 text

class SpeakersListPresenter(val speakers: GetSpeakers) { lateinit var view: ISpeakersListView fun attachView(appView: ISpeakersListView) { view = appView fetchSpeakersList() } … presenter src/commonMain/presentation/SpeakersListPresenter.kt android business logic model parser network presentation view

Slide 66

Slide 66 text

interface ISpeakerEvent { fun onNewList(speakers: List) fun onNewListFailed(e: Exception) } presenter src/commonMain/presentation/ISpeakerEvent.kt android business logic model parser network presentation view

Slide 67

Slide 67 text

class SpeakersListPresenter(val speakers: GetSpeakers) { lateinit var view: ISpeakersListView fun attachView(appView: ISpeakersListView) { view = appView fetchSpeakersList() } … presenter src/commonMain/presentation/SpeakersListPresenter.kt android business logic model parser network presentation view onCreate()/ viewDidLoad()

Slide 68

Slide 68 text

fun fetchSpeakersList() { PresenterCoroutineScope(defaultDispatcher).launch { speakers( onSuccess = { view.onSpeakersListFetched(it) }, onFailure = { view.onSpeakersListFailed(it) }) } } presenter src/commonMain/presentation/SpeakersListPresenter.kt android business logic model parser network presentation view

Slide 69

Slide 69 text

class GetSpeakers(val commitAPI: CommitAPI) { suspend operator fun invoke( onSuccess: (List) -> Unit, onFailure: (Exception) -> Unit) { val result = commitAPI.fetchSpeakers() coroutineScope { launch(uiDispatcher) { try { onSuccess(result.speakers) } catch (e: Exception) { onFailure(e) } … } domain src/commonMain/domain/GetSpeakers.kt android business logic model parser network presentation view

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

class MainActivity : AppCompatActivity(), ISpeakersEvent { val presenter by lazy { ServiceLocator.getPresenter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) presenter.attachView(this) } override fun onNewList(speakers: List) { setUiComponents(speakers) } ... android src/commonAndroid/presentation/MainActivity.kt android business logic model parser network presentation view

Slide 72

Slide 72 text

class MainActivity : AppCompatActivity(), ISpeakersEvent { val presenter by lazy { ServiceLocator.getPresenter } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) presenter.attachView(this) } override fun onNewList(speakers: List) { setUiComponents(speakers) } ... android src/commonAndroid/presentation/MainActivity.kt android business logic model parser network presentation view

Slide 73

Slide 73 text

object ServiceLocator { val commitApi = CommitAPI(PlatformServiceLocator.httpClientEngine) val getPresenter: SpeakersListPresenter get() = SpeakersListPresenter(GetSpeakers(commitApi)) } expect object PlatformServiceLocator { val httpClientEngine: HttpClientEngine } init src/commonMain/ServiceLocator.kt android business logic model parser network presentation view

Slide 74

Slide 74 text

actual object PlatformServiceLocator { actual val httpClientEngine: HttpClientEngine by lazy { OkHttp.create () } } init src/mainAndroid/PlatformServiceLocator.kt android business logic model parser network presentation view

Slide 75

Slide 75 text

actual object PlatformServiceLocator { actual val httpClientEngine: HttpClientEngine by lazy { Ios.create() } } init src/iosMain/PlatformServiceLocator.kt iOS business logic model parser network presentation view

Slide 76

Slide 76 text

override fun onBindViewHolder(viewHolder: SpeakerViewHolder, position: Int) { val speaker = speakers[position] Glide.with(viewHolder.speakerPhoto) .load(speaker.img) .apply(RequestOptions.circleCropTransform()) .into(viewHolder.speakerPhoto) viewHolder.speakerName.text = speaker.speaker viewHolder.talkTitle.text = speaker.talkTitle viewHolder.container.setOnClickListener { action.onUserClickAction(speaker, it) } } android src/mainAndroid/presentation/SpeakersListAdapter.kt android business logic model parser network presentation view

Slide 77

Slide 77 text

override fun onBindViewHolder(viewHolder: SpeakerViewHolder, position: Int) { val speaker = speakers[position] Glide.with(viewHolder.speakerPhoto) .load(speaker.img) .apply(RequestOptions.circleCropTransform()) .into(viewHolder.speakerPhoto) viewHolder.speakerName.text = speaker.speaker viewHolder.talkTitle.text = speaker.talkTitle viewHolder.container.setOnClickListener { action.onUserClickAction(speaker, it) } } android src/mainAndroid/presentation/SpeakersListAdapter.kt android business logic model parser network presentation view you can keep using your android libraries

Slide 78

Slide 78 text

class SpeakerTableViewController: UITableViewController, ISpeakersListView { lazy var presenter = ServiceLocator.init().getPresenter var speakers = [Speaker]() override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) presenter.attachView(view: self) } … iOS iosApp/iosApp/SpeakerTableViewController.swift iOS business logic model parser network presentation view

Slide 79

Slide 79 text

class SpeakerTableViewController: UITableViewController, ISpeakersListView { lazy var presenter = ServiceLocator.init().getPresenter var speakers = [Speaker]() override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) presenter.attachView(view: self) } … iOS iosApp/iosApp/SpeakerTableViewController.swift iOS business logic model parser network presentation view

Slide 80

Slide 80 text

func onSpeakersListFetched(speakers: [Speaker]) { self.speakers = speakers self.tableView.reloadData() } iOS iosApp/iosApp/SpeakerTableViewController.swift iOS business logic model parser network presentation view

Slide 81

Slide 81 text

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellIdentifier = "SpeakerTableViewCell" let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as SpeakerTableViewCell let speaker = speakers[indexPath.row] cell.talkName.text = speaker.talkTitle cell.speakerName.text = speaker.speaker cell.speakerImage.image = speaker.img return cell } iOS iosApp/iosApp/SpeakerTableViewController.swift iOS business logic model parser network presentation view

Slide 82

Slide 82 text

conclusions don’t forget to bring your own towel.

Slide 83

Slide 83 text

- it’s in experimental state - although there are projects in production - you can spend some time resolving compilation issues - specially if you try to target all platforms - not possible to debug kotlin from Xcode - lookout for plugins/ libraries updates (in progress) Kotlin Multiplatform

Slide 84

Slide 84 text

- strong community - a lot of people are using kotlin nowadays - Google and JetBrains are pushing Kotlin in - you can ask questions directly on https://kotlinlang.slack.com - 2x faster to develop your features business logic - 2x faster writing unit tests - one tech stack - consistency across platforms (conclusions) Kotlin Multiplatform

Slide 85

Slide 85 text

- be extremely careful with all updates - IDEA, jdk, kotlin, libraries - everything. - start small, don’t try to reach 100% of shared logic - keep versioning in mind - remember that’s still on experimental state (suggestions) Kotlin Multiplatform

Slide 86

Slide 86 text

- Kotlin Slack - Android @ Portugal Slack - Kotlin Official - Kotlin Training - Kotlin by: https://jakewharton.com/presentations/ http://antonioleiva.com/kotlin (useful links) more information

Slide 87

Slide 87 text

@cafonsomota so long and thanks for all the fish