shared codebase with / Native Oleksandr Yefremov
shared codebase with / Native / Multiplatform
The Plan • Why multiplatform • Question of the day ! • What we have in common • Typical mobile app structure • Existing multi/crossplatform solutions • Kotlin/Native Multiplatform • K/N vs K/MPP. artifacts • expect-actual. objc/swift interop • How do I implement… • Multithreading • iOS specifics • How K/MPP is different • Main issues " • Conclusion
Why multiplatform ✅ Save costs on engineering ✅ Reduce release cycle ✅ Increase quality (less code → fewer bugs) … $ Poor runtime performance % Crossplatform (== painful) debugging & Harder to recruit and retain developers …
Why multiplatform ⍰ Why try Kotlin/MPP ? If Kotlin team creates a programming system which allows sharing code on Android and iOS and will be convenient to use it mostly probably is worth trying out And because it's fun! '
Question of the day A lot of information, some things had to be left out Ask further questions during networking session Will it fly? ! ⚠
Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) Share the whole app one language platform specific code + Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) Share business logicvs + native UI platform specific code + Typical mobile app structure
Share the whole app Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) one language platform specific code + Share business logicvs Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) + native UI platform specific code + Typical mobile app structure
Kotlin/MPP is not a single framework but a programming system which includes • kotlin as a language • kotlin-multiplatform & kotlin-native gradle plugins • kotlin-native compiler & runtime (aka konan) • package management based on maven • multiplatform stdlib (kotlinx) and 3rd party libraries
Kotlin/MPP helps create a layer of shared business logic* and seamlessly integrate it with platform specific code and native UI on each platform. It deliberately does not aim for common UI or WORA (write once run anywhere) * here business logic just means code that is not UI related, e.g. connectivity, persistence, data handling etc.
Kotlin/MPP https://kotlinlang.org/docs/reference/multiplatform.html
Share the whole app Share business logicvs
Flutter ? Share the whole app Share business logicvs ¯_( )_/¯
Kotlin/MPP can be easily integrated into existing code • add kotlin-multiplatform gradle configuration • write MyBusinessLogic.kt • ./gradlew publish • on iOS add myAwesomeLib.framework to Xcode project and easily removed • remove myNotSoAwesomeLib.framework from project
Kotlin/MPP can be easily integrated into existing code • add kotlin-multiplatform gradle configuration • write MyBusinessLogic.kt • ./gradlew publish • Add myAwesomeLib.framework to Xcode project and easily removed • remove myNotSoAwesomeLib.framework from project Experiment friendly! Easy to remove!
kotlin-multiplatform (aka common) kotlin-jvm kotlin-native kotlin-js Kotlin/MPP
kotlin-multiplatform (aka common) kotlin-jvm kotlin-native kotlin-js .so + JNI Kotlin/MPP .framework .dll .dylib .exe
.so + JNI kotlin-multiplatform (aka common) kotlin-jvm kotlin-native kotlin-js Kotlin/MPP
kotlin-multiplatform (aka common) .jar .aar .jar.klib + .module./gradlew publish kotlin-jvm kotlin-native kotlin-js .so + JNI Kotlin/MPP .framework .dll .dylib .exe
Kotlin/MPP https://github.com/touchlab/Stately https://repo1.maven.org/maven2/co/touchlab/
// common expect fun writeLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } Kotlin/MPP expect - actual
// common expect fun writeLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } Kotlin/MPP expect - actual
// common expect fun writeLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } expect - actual Kotlin/MPP
// common expect fun platformName(): String // android actual fun platformName(): String { return android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL } // ios // system frameworks are pre-imported import platform.UIKit.UIDevice actual fun platformName(): String { return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } expect - actual Kotlin/MPP
// common expect fun platformName(): String // android actual fun platformName(): String { return android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL } // ios // system frameworks are pre-imported import platform.UIKit.UIDevice actual fun platformName(): String { return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } expect - actual Kotlin/MPP
// common package example object Object { val field = "A" } interface Interface { fun iMember() {} } class Clazz : Interface { fun method(someClass: SomeObjcClass): ULong? = 42UL } fun acceptFun(block: (String) -> String?) = block("block is lambda!") fun supplyFun() : (String) -> String? = { "$it is cool!" } ObjC/Swift interop Kotlin/MPP
// common package example object Object { val field = "A" } interface Interface { fun iMember() {} } class Clazz : Interface { fun method(someClass: SomeObjcClass): ULong? = 42UL } fun acceptFun(block: (String) -> String?) = block("block is lambda!") fun supplyFun() : (String) -> String? = { "$it is cool!" } ObjC/Swift interop Kotlin/MPP
// ios import Foundation import Demo let kotlinObject = Object() assert(kotlinObject === Object(), "Kotlin object has only one instance") let field = Object().field let clazz = Clazz() clazz.method(someClass: SomeObjcClass()) let ret = LibKt.acceptFun { "($0) Kotlin is fun" } if (ret != nil) { print(ret!) } ObjC/Swift interop Kotlin/MPP
// ios import Foundation import Demo let kotlinObject = Object() assert(kotlinObject === Object(), "Kotlin object has only one instance") let field = Object().field let clazz = Clazz() clazz.method(someClass: SomeObjcClass()) let ret = LibKt.acceptFun { "($0) Kotlin is fun" } if (ret != nil) { print(ret!) } ObjC/Swift interop Kotlin/MPP
Data model Persistence Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Share business logic Kotlin/MPP
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Persistence Share business logic Kotlin/MPP
Networking Kotlin/MPP Ktor is a framework for building asynchronous servers and clients in connected systems using the powerful Kotlin programming language. Ktor directly supports Raw Sockets, HTTP Clients and WebSockets. Using Raw Sockets it is possible to implement clients with higher level protocols. https://ktor.io/clients/index.html
Networking Kotlin/MPP Supported platforms are JVM, Android and iOS, but in future versions, there will be more supported
Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal class IosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal class IosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal class IosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Persistence Share business logic Kotlin/MPP
Kotlin/MPPPersistence
Kotlin/MPPPersistence - or -
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Kotlin/MPPData model 1. use classes that are available in common 2. expect in common, actual in platform impl. Use cases sealed classes are not as useful on iOS 
 as on Android )
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Kotlin/MPPSerialization
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Kotlin/MPPMVx (P, VM, I, U)
Kotlin/MPPMVx (P, VM, I, U) expect - actual MVP
Kotlin/MPPMVx (P, VM, I, U) 404 MVVM
Kotlin/MPPMVx (P, VM, I, U) MVI Unidirectional architecture pattern based on reactive event streams
Kotlin/MPPMVx (P, VM, I, U) MVI
Kotlin/MPPMVx (P, VM, I, U) MVI
Kotlin/MPPMVx (P, VM, I, U) expect - actual MVU
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Kotlin/MPPWiring up (DI, SL) - Dagger 2 ? - No. It's JVM only a smart Service Locator, not a "real" DI
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Kotlin/MPPUnit and integr. tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
Kotlin/MPPUnit and integr. tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
Kotlin/MPPUnit and integr. tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
Kotlin/MPPUnit and integr. tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
Kotlin/MPPUnit and integr. tests No mocking frameworks yet ) Kotlin team helps in porting MockK
Data model Use cases Utilities MVx (P, VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
Multithreading Kotlin/MPP is hard Convenient multithreading on different OS × different targets (JVM, native binary, JS) is harder.
Multithreading Kotlin/MPP
Multithreading Kotlin/MPP
Multithreading Kotlin/MPP that's all you need to know about multithreading in K/N for now
Multithreading Kotlin/MPP Bad news: you need to deal with • object freezing and InvalidMutabilityException • Workers • @ThreadLocal / @SharedGlobal • AtomicRef • coroutines that run only on main thread If you want to use it today
Bad news: you need to deal with • object freezing and InvalidMutabilityException • Workers • @ThreadLocal / @SharedGlobal • AtomicRef • coroutines that run only on main thread Multithreading Kotlin/MPP If you want to use it today
Multithreading Kotlin/MPP Good news: • in most cases you need async, not MT If you want to use it today
Multithreading Kotlin/MPP If you want to use it today Good news: • in most cases you need async, not MT • coroutines are planned to be reworked 
 to support MT in K/N
iOS specifics Kotlin/MPP • K/N compiler produces .framework (or static .a) • Emits DWARF (full debug support in Xcode) • AppCode supports* completion and debugging • system frameworks, like UIKit, are pre-linked 
 and can be used out of the box • community CocoaPods plugin** * almost. WIP ** https://github.com/AlecStrong/kotlin-native-cocoapods
MPP Platform native code only primitives or RCTConvert / RCTDeviceEventEmitter via C interface only primitives or BasicMethodChannel iOS: generates real ObjC headers in .framework How K/MPP is different (IMO)
How K/MPP is different (IMO) is a lower level language proper replacement for C++
How K/MPP is different (IMO) is a lower level language proper replacement for C++
How K/MPP is different (IMO) are all about about unified UI and reducing development cycle (hot reload) which is a perfectly valid case
How K/MPP is different Kotlin/MPP (IMO) is an application level programming system which aims to be a foundation for shared business logic layer but within a native app
How K/MPP is different (IMO) + https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1
How K/MPP is different (IMO) https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1
Main issues Kotlin/MPP • K/N compiler performance ๏ compilation for iOS is slow and not incremental ๏ Android Instant Run is fine ✅ • IDEs and plugins are not perfect ๏ and their versions often don't match ๏ …but we are getting there • Multithreading is not straightforward • Bunch of other lesser and bigger annoying things 
 you find when working with new technology
Question of the day Will it fly? !
Question of the day • Under active development • Well-known adopters and contributors …and others SQLDelight CocoaPods plugin Timber Stately DroidCon app
Question of the day • Under active development • Well-known adopters and contributors • Kotlin team is actively helping
Question of the day • Under active development • Well-known adopters and contributors • Kotlin team is actively helping • Mobile support is Tier 1 • No bridge == native performance • Slack channel where you can ask anything https://slack.kotlinlang.org/
!
Q & A Thank you! !
We're hiring! https://www.prosiebensat1-jobs.com/eng
Official repo - https://github.com/JetBrains/kotlin-native Fast Prototypes with Flutter + Kotlin/Native - https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1 DroidconKotlin app written with Kotlin/MPP - https://github.com/touchlab/DroidconKotlin Blogpost about that app - https://medium.com/@kpgalligan/droidcon-nyc-on-ios-with-kotlin-native-5a6a2749057e Example News app - https://github.com/tokenlab/kotlin-native-multiplatform-news Example app - https://github.com/wupdigital/kotlin-native-superhero-app Write and deploy a Kotlin library compatible with Android and iOS - https://proandroiddev.com/write-and-deploy-a-kotlin- library-compatible-with-android-and-ios-48415b49ebed Kotlin Multiplatform. Very beginner’s guide (part 1) - https://proandroiddev.com/kotlin-multiplatform-very-beginners-guide- part-1-6419f74afa0f K/MPP JetBrains libraries: https://ktor.io/clients/http-client/multiplatform.html https://github.com/Kotlin/kotlinx.serialization K/MPP community libraries: https://github.com/touchlab/SQLiter https://github.com/touchlab/Stately https://github.com/badoo/Reaktive https://github.com/florent37/Multiplatform-Preferences https://github.com/Kodein-Framework/Kodein-DI https://github.com/AlecStrong/kotlin-native-cocoapods Reaktor K/N issue - https://github.com/reactor/reactor-core/issues/979 K/N Stranger Threads part 1 - https://medium.com/@kpgalligan/kotlin-native-stranger-threads-ep-1-1ccccdfe0c99 K/N Stranger Threads part 2 - https://medium.com/@kpgalligan/kotlin-native-stranger-threads-ep-2-208523d63c8f Further reading
© Copyrights, copylefts Some images, logos and code snippets may be property of their respective owners and are used only in educational purposes

Multiplatform shared codebase with Kotlin/Native - UA Mobile 2019

  • 1.
    shared codebase with /Native Oleksandr Yefremov
  • 2.
    shared codebase with /Native / Multiplatform
  • 3.
    The Plan • Whymultiplatform • Question of the day ! • What we have in common • Typical mobile app structure • Existing multi/crossplatform solutions • Kotlin/Native Multiplatform • K/N vs K/MPP. artifacts • expect-actual. objc/swift interop • How do I implement… • Multithreading • iOS specifics • How K/MPP is different • Main issues " • Conclusion
  • 4.
    Why multiplatform ✅ Savecosts on engineering ✅ Reduce release cycle ✅ Increase quality (less code → fewer bugs) … $ Poor runtime performance % Crossplatform (== painful) debugging & Harder to recruit and retain developers …
  • 5.
    Why multiplatform ⍰ Whytry Kotlin/MPP ? If Kotlin team creates a programming system which allows sharing code on Android and iOS and will be convenient to use it mostly probably is worth trying out And because it's fun! '
  • 6.
    Question of theday A lot of information, some things had to be left out Ask further questions during networking session Will it fly? ! ⚠
  • 7.
    Data model Networking Persistence Unitand integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) Share the whole app one language platform specific code + Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) Share business logicvs + native UI platform specific code + Typical mobile app structure
  • 8.
    Share the wholeapp Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) one language platform specific code + Share business logicvs Data model Networking Persistence Unit and integr. tests UI UI tests Serialization Use cases Utilities MVx (P, VM, I, U) Wiring up (DI, SL) + native UI platform specific code + Typical mobile app structure
  • 9.
    Kotlin/MPP is not asingle framework but a programming system which includes • kotlin as a language • kotlin-multiplatform & kotlin-native gradle plugins • kotlin-native compiler & runtime (aka konan) • package management based on maven • multiplatform stdlib (kotlinx) and 3rd party libraries
  • 10.
    Kotlin/MPP helps create alayer of shared business logic* and seamlessly integrate it with platform specific code and native UI on each platform. It deliberately does not aim for common UI or WORA (write once run anywhere) * here business logic just means code that is not UI related, e.g. connectivity, persistence, data handling etc.
  • 11.
  • 12.
    Share the wholeapp Share business logicvs
  • 13.
    Flutter ? Share thewhole app Share business logicvs ¯_( )_/¯
  • 14.
    Kotlin/MPP can be easilyintegrated into existing code • add kotlin-multiplatform gradle configuration • write MyBusinessLogic.kt • ./gradlew publish • on iOS add myAwesomeLib.framework to Xcode project and easily removed • remove myNotSoAwesomeLib.framework from project
  • 15.
    Kotlin/MPP can be easilyintegrated into existing code • add kotlin-multiplatform gradle configuration • write MyBusinessLogic.kt • ./gradlew publish • Add myAwesomeLib.framework to Xcode project and easily removed • remove myNotSoAwesomeLib.framework from project Experiment friendly! Easy to remove!
  • 16.
  • 17.
    kotlin-multiplatform (aka common) kotlin-jvm kotlin-nativekotlin-js .so + JNI Kotlin/MPP .framework .dll .dylib .exe
  • 18.
    .so + JNI kotlin-multiplatform (akacommon) kotlin-jvm kotlin-native kotlin-js Kotlin/MPP
  • 19.
    kotlin-multiplatform (aka common) .jar .aar .jar.klib +.module./gradlew publish kotlin-jvm kotlin-native kotlin-js .so + JNI Kotlin/MPP .framework .dll .dylib .exe
  • 20.
  • 21.
    // common expect funwriteLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } Kotlin/MPP expect - actual
  • 22.
    // common expect funwriteLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } Kotlin/MPP expect - actual
  • 23.
    // common expect funwriteLogMessage(tag: String, message: String) // android actual fun writeLogMessage(tag: String, message: String) { Log.d(tag, message) } // ios actual fun writeLogMessage(tag: String, message: String) { print(tag + " : " + message) } expect - actual Kotlin/MPP
  • 24.
    // common expect funplatformName(): String // android actual fun platformName(): String { return android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL } // ios // system frameworks are pre-imported import platform.UIKit.UIDevice actual fun platformName(): String { return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } expect - actual Kotlin/MPP
  • 25.
    // common expect funplatformName(): String // android actual fun platformName(): String { return android.os.Build.MANUFACTURER + " " + android.os.Build.MODEL } // ios // system frameworks are pre-imported import platform.UIKit.UIDevice actual fun platformName(): String { return UIDevice.currentDevice.systemName() + " " + UIDevice.currentDevice.systemVersion } expect - actual Kotlin/MPP
  • 26.
    // common package example objectObject { val field = "A" } interface Interface { fun iMember() {} } class Clazz : Interface { fun method(someClass: SomeObjcClass): ULong? = 42UL } fun acceptFun(block: (String) -> String?) = block("block is lambda!") fun supplyFun() : (String) -> String? = { "$it is cool!" } ObjC/Swift interop Kotlin/MPP
  • 27.
    // common package example objectObject { val field = "A" } interface Interface { fun iMember() {} } class Clazz : Interface { fun method(someClass: SomeObjcClass): ULong? = 42UL } fun acceptFun(block: (String) -> String?) = block("block is lambda!") fun supplyFun() : (String) -> String? = { "$it is cool!" } ObjC/Swift interop Kotlin/MPP
  • 28.
    // ios import Foundation importDemo let kotlinObject = Object() assert(kotlinObject === Object(), "Kotlin object has only one instance") let field = Object().field let clazz = Clazz() clazz.method(someClass: SomeObjcClass()) let ret = LibKt.acceptFun { "($0) Kotlin is fun" } if (ret != nil) { print(ret!) } ObjC/Swift interop Kotlin/MPP
  • 29.
    // ios import Foundation importDemo let kotlinObject = Object() assert(kotlinObject === Object(), "Kotlin object has only one instance") let field = Object().field let clazz = Clazz() clazz.method(someClass: SomeObjcClass()) let ret = LibKt.acceptFun { "($0) Kotlin is fun" } if (ret != nil) { print(ret!) } ObjC/Swift interop Kotlin/MPP
  • 30.
    Data model Persistence Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Share business logic Kotlin/MPP
  • 31.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Persistence Share business logic Kotlin/MPP
  • 32.
    Networking Kotlin/MPP Ktor isa framework for building asynchronous servers and clients in connected systems using the powerful Kotlin programming language. Ktor directly supports Raw Sockets, HTTP Clients and WebSockets. Using Raw Sockets it is possible to implement clients with higher level protocols. https://ktor.io/clients/index.html
  • 33.
    Networking Kotlin/MPP Supported platformsare JVM, Android and iOS, but in future versions, there will be more supported
  • 34.
    Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal classIosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
  • 35.
    Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal classIosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
  • 36.
    Networking Kotlin/MPP https://github.com/ktorio/ktor/blob/master/ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/IosClientEngine.kt internal classIosClientEngine(override val config: IosClientEngineConfig) : HttpClientEngine { override val dispatcher: CoroutineDispatcher override val coroutineContext: CoroutineContext suspendCancellableCoroutine { continuation -> val callContext = coroutineContext + CompletableDeferred<Unit>() override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) { ... }
  • 37.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 38.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Networking Persistence Share business logic Kotlin/MPP
  • 39.
  • 40.
  • 41.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 42.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 43.
    Kotlin/MPPData model 1. useclasses that are available in common 2. expect in common, actual in platform impl. Use cases sealed classes are not as useful on iOS 
 as on Android )
  • 44.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 45.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 46.
  • 47.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 48.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 49.
  • 50.
    Kotlin/MPPMVx (P, VM, I,U) expect - actual MVP
  • 51.
  • 52.
    Kotlin/MPPMVx (P, VM, I,U) MVI Unidirectional architecture pattern based on reactive event streams
  • 53.
  • 54.
  • 55.
    Kotlin/MPPMVx (P, VM, I,U) expect - actual MVU
  • 56.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 57.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 58.
    Kotlin/MPPWiring up (DI, SL) -Dagger 2 ? - No. It's JVM only a smart Service Locator, not a "real" DI
  • 59.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 60.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 61.
    Kotlin/MPPUnit and integr.tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
  • 62.
    Kotlin/MPPUnit and integr.tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
  • 63.
    Kotlin/MPPUnit and integr.tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
  • 64.
    Kotlin/MPPUnit and integr.tests kotlin.apply { sourceSets { commonMain.dependencies { implementation kotlin('stdlib-common') } commonTest.dependencies { implementation kotlin('test-common') implementation kotlin('test-annotations-common') } jvmMain.dependencies { implementation kotlin('stdlib-jdk8') } jvmTest.dependencies { implementation kotlin('test') implementation kotlin('test-junit') } } }
  • 65.
    Kotlin/MPPUnit and integr.tests No mocking frameworks yet ) Kotlin team helps in porting MockK
  • 66.
    Data model Use cases Utilities MVx (P,VM, I, U) Unit and integr. tests UI UI tests (interop w/ platform) Wiring up (DI, SL) Serialization Kotlin + Persistence Share business logic Kotlin/MPP Networking
  • 67.
    Multithreading Kotlin/MPP is hard Convenient multithreadingon different OS × different targets (JVM, native binary, JS) is harder.
  • 68.
  • 69.
  • 70.
    Multithreading Kotlin/MPP that's all youneed to know about multithreading in K/N for now
  • 71.
    Multithreading Kotlin/MPP Bad news: youneed to deal with • object freezing and InvalidMutabilityException • Workers • @ThreadLocal / @SharedGlobal • AtomicRef • coroutines that run only on main thread If you want to use it today
  • 72.
    Bad news: youneed to deal with • object freezing and InvalidMutabilityException • Workers • @ThreadLocal / @SharedGlobal • AtomicRef • coroutines that run only on main thread Multithreading Kotlin/MPP If you want to use it today
  • 73.
    Multithreading Kotlin/MPP Good news: • inmost cases you need async, not MT If you want to use it today
  • 74.
    Multithreading Kotlin/MPP If you wantto use it today Good news: • in most cases you need async, not MT • coroutines are planned to be reworked 
 to support MT in K/N
  • 75.
    iOS specifics Kotlin/MPP • K/Ncompiler produces .framework (or static .a) • Emits DWARF (full debug support in Xcode) • AppCode supports* completion and debugging • system frameworks, like UIKit, are pre-linked 
 and can be used out of the box • community CocoaPods plugin** * almost. WIP ** https://github.com/AlecStrong/kotlin-native-cocoapods
  • 76.
    MPP Platform native code onlyprimitives or RCTConvert / RCTDeviceEventEmitter via C interface only primitives or BasicMethodChannel iOS: generates real ObjC headers in .framework How K/MPP is different (IMO)
  • 77.
    How K/MPP isdifferent (IMO) is a lower level language proper replacement for C++
  • 78.
    How K/MPP isdifferent (IMO) is a lower level language proper replacement for C++
  • 79.
    How K/MPP isdifferent (IMO) are all about about unified UI and reducing development cycle (hot reload) which is a perfectly valid case
  • 80.
    How K/MPP isdifferent Kotlin/MPP (IMO) is an application level programming system which aims to be a foundation for shared business logic layer but within a native app
  • 81.
    How K/MPP isdifferent (IMO) + https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1
  • 82.
    How K/MPP isdifferent (IMO) https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1
  • 83.
    Main issues Kotlin/MPP • K/Ncompiler performance ๏ compilation for iOS is slow and not incremental ๏ Android Instant Run is fine ✅ • IDEs and plugins are not perfect ๏ and their versions often don't match ๏ …but we are getting there • Multithreading is not straightforward • Bunch of other lesser and bigger annoying things 
 you find when working with new technology
  • 84.
    Question of theday Will it fly? !
  • 85.
    Question of theday • Under active development • Well-known adopters and contributors …and others SQLDelight CocoaPods plugin Timber Stately DroidCon app
  • 86.
    Question of theday • Under active development • Well-known adopters and contributors • Kotlin team is actively helping
  • 87.
    Question of theday • Under active development • Well-known adopters and contributors • Kotlin team is actively helping • Mobile support is Tier 1 • No bridge == native performance • Slack channel where you can ask anything https://slack.kotlinlang.org/
  • 88.
  • 89.
  • 90.
  • 91.
    Official repo -https://github.com/JetBrains/kotlin-native Fast Prototypes with Flutter + Kotlin/Native - https://tech.olx.com/fast-prototypes-with-flutter-kotlin-native-d7ce5cfeb5f1 DroidconKotlin app written with Kotlin/MPP - https://github.com/touchlab/DroidconKotlin Blogpost about that app - https://medium.com/@kpgalligan/droidcon-nyc-on-ios-with-kotlin-native-5a6a2749057e Example News app - https://github.com/tokenlab/kotlin-native-multiplatform-news Example app - https://github.com/wupdigital/kotlin-native-superhero-app Write and deploy a Kotlin library compatible with Android and iOS - https://proandroiddev.com/write-and-deploy-a-kotlin- library-compatible-with-android-and-ios-48415b49ebed Kotlin Multiplatform. Very beginner’s guide (part 1) - https://proandroiddev.com/kotlin-multiplatform-very-beginners-guide- part-1-6419f74afa0f K/MPP JetBrains libraries: https://ktor.io/clients/http-client/multiplatform.html https://github.com/Kotlin/kotlinx.serialization K/MPP community libraries: https://github.com/touchlab/SQLiter https://github.com/touchlab/Stately https://github.com/badoo/Reaktive https://github.com/florent37/Multiplatform-Preferences https://github.com/Kodein-Framework/Kodein-DI https://github.com/AlecStrong/kotlin-native-cocoapods Reaktor K/N issue - https://github.com/reactor/reactor-core/issues/979 K/N Stranger Threads part 1 - https://medium.com/@kpgalligan/kotlin-native-stranger-threads-ep-1-1ccccdfe0c99 K/N Stranger Threads part 2 - https://medium.com/@kpgalligan/kotlin-native-stranger-threads-ep-2-208523d63c8f Further reading
  • 92.
    © Copyrights, copylefts Someimages, logos and code snippets may be property of their respective owners and are used only in educational purposes