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

The Hitchhikers Guide Through Kotlin Multiplatform

D8a3623b157508fecdae1f8e756f362f?s=47 cmota
June 21, 2019

The Hitchhikers Guide Through Kotlin Multiplatform

Since the early days of mobile that we keep seeing new frameworks being designed to overcome one of the biggest challenges:
- How can I develop for both Android and iOS?

Although it’s initial promises, when we talk about performance, maintainability or even customization we keep discarding these solutions and we always choose native.

Fast forward to the present, and now we have two new languages: Android is Kotlin first and iOS, Swift. And if you put them side by side you can see a lot of similarities between both what will ease switching between one to the other if you have to develop for both platforms.

But what I told that you could just develop in Kotlin and run it seamlessly on all devices? Here comes Kotlin Multiplatform!

D8a3623b157508fecdae1f8e756f362f?s=128

cmota

June 21, 2019
Tweet

Transcript

  1. Kotlin Multiplatform

  2. The Hitchhikers Guide Through Kotlin Multiplatform The Hitchhikers Guide Through

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

  4. None
  5. 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.”
  6. android iOS

  7. Dark Theme

  8. android iOS

  9. Photo by Fabian Grohs on Unsplash

  10. Photo by Fabian Grohs on Unsplash a wild application idea

    appears! develop it for Android and iOS.
  11. -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
  12. ~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
  13. Photo by Fabian Grohs on Unsplash a wild application idea

    appears! develop it for Android and iOS and web.
  14. ~3xthe team the cost the status meetings required the time

    spent on development the time spent on testing the time spent on bug fixing
  15. None
  16. let’s find a solution that works on all platforms.

  17. 2008 2012 2018 2013 2011 2017 2006 2010 2009 2015

    * Kotlin Multiplatform *
  18. - smaller team - typically half of the cost needed

    on native - small learning curve for web developers (advantages) Cross-platform
  19. - 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
  20. how can we have the best of both worlds?

  21. how can we have the best of both worlds?

  22. kotlin “42.”

  23. None
  24. - 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
  25. Mutability etc. Null safety Default values Type inference String interpolation

    when Collections
  26. NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException NullPointerException TransactionTooLargeException

  27. public class Conference { private String mName; private String mLocal;

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

    techs: List<String>) (less code) Concise Conference.kt
  29. Less bugs! more free time (and happier team… and management)

    (less code) Concise
  30. -getOrElse() -find() -filter() -filterNot() -filterNotNull() -flatMap() -mapNotNull() -all() -any() -sumBy()

    -zip() -… -take() -takeLast() -sortBy() -sortByDescending() -groupBy() -map() (collections) Language features
  31. 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
  32. > [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()
 

  33. > [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
  34. > [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
  35. - small learning curve involved - easily to go from

    JavaScript/ Swift into Kotlin and back (from a developers’ point of view) Easy to learn
  36. 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
  37. 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
  38. kotlin multiplatform “‘Resistance is useless!’ How can anyone maintain a

    positive mental attitude if you’re saying things like that?”
  39. K otlin multiplatform using kotlin in projects that target more

    than one platform
  40. (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
  41. first reaction

  42. 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
  43. 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
  44. android iOS web desktop model parser network presentation common view

    view view view java/kotlin objective-c/ swift (kotlin) JS supported in jvm
  45. but how can they expect to communicate?

  46. declared at common module expect declared at android module actual

    declared at iOS module declared at …
  47. we want a platform-specific value for name

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

  49. commonMain src/commonMain/sample/Platform.kt - define actual on android - define actual

    on iOS targets: android and iOS expect object Platform { val name: String }
  50. 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
  51. IntelliJ will ask you declare the implementations for actual

  52. *.kt common expect JVM actual *.kt, *.java, *.jar Native actual

    *.kt, *C, Swift, Framework JS actual *.kt, *.js, NPM
  53. medium.com/@cafonsomota

  54. demo "For a moment, nothing happened. Then, after a second

    or so, nothing continued to happen.”
  55. github.com/cmota/commit19

  56. - 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
  57. android iOS Retrofit Alamofire GSON/ Moshi JSONSerialization MVP, MVVM, MVI

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

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

    RxJava RxSwift Tests Tests android iOS Activity UIViewController RecyclerView UITableView unnecessary duplication
  60. class CommitAPI(engine: HttpClientEngine) { private val client = HttpClient(engine) {

    install(JsonFeature) { serializer = KotlinxSerializer() } } suspend fun fetchSpeakers(): AllSpeakersEntity { val response = client.get<HttpResponse>{ 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
  61. class CommitAPI(engine: HttpClientEngine) { private val client = HttpClient(engine) {

    install(JsonFeature) { serializer = KotlinxSerializer() } } suspend fun fetchSpeakers(): AllSpeakersEntity { val response = client.get<HttpResponse>{ 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
  62. { “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
  63. { "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
  64. @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
  65. 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
  66. interface ISpeakerEvent { fun onNewList(speakers: List<Speaker>) fun onNewListFailed(e: Exception) }

    presenter src/commonMain/presentation/ISpeakerEvent.kt android business logic model parser network presentation view
  67. 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()
  68. 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
  69. class GetSpeakers(val commitAPI: CommitAPI) { suspend operator fun invoke( onSuccess:

    (List<Speaker>) -> 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
  70. None
  71. 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<Speaker>) { setUiComponents(speakers) } ... android src/commonAndroid/presentation/MainActivity.kt android business logic model parser network presentation view
  72. 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<Speaker>) { setUiComponents(speakers) } ... android src/commonAndroid/presentation/MainActivity.kt android business logic model parser network presentation view
  73. 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
  74. actual object PlatformServiceLocator { actual val httpClientEngine: HttpClientEngine by lazy

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

    { Ios.create() } } init src/iosMain/PlatformServiceLocator.kt iOS business logic model parser network presentation view
  76. 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
  77. 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
  78. 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
  79. 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
  80. func onSpeakersListFetched(speakers: [Speaker]) { self.speakers = speakers self.tableView.reloadData() } iOS

    iosApp/iosApp/SpeakerTableViewController.swift iOS business logic model parser network presentation view
  81. 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
  82. conclusions don’t forget to bring your own towel.

  83. - 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
  84. - 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
  85. - 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
  86. - Kotlin Slack - Android @ Portugal Slack - Kotlin

    Official - Kotlin Training - Kotlin by: https://jakewharton.com/presentations/ http://antonioleiva.com/kotlin (useful links) more information
  87. @cafonsomota so long and thanks for all the fish