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

Kotlin Multiplatform: Sharing code between Android and iOS

Kotlin Multiplatform: Sharing code between Android and iOS

Wellington Costa

May 28, 2020
Tweet

More Decks by Wellington Costa

Other Decks in Programming

Transcript

  1. It’s an open source project developed and maintained by Jetbrains

    and some companies such as Square and Touchlab, that enables optional code sharing for several platforms, natively integrated, and based on Kotlin Programming Language. What is Kotlin Multiplatform?
  2. It’s an open source project developed and maintained by Jetbrains

    and some companies such as Square and Touchlab, that enables optional code sharing for several platforms, natively integrated, and based on Kotlin Programming Language. The main advantage is the capability of write Kotlin code, e.g. business code, that can be shared to several platforms, and compile it to native code, saving efforts to write the same code in different languages for each platforms. What is Kotlin Multiplatform?
  3. expect/actual mechanism "// In common code expect val isMainThread: Boolean

    "// In Android/JVM actual val isMainThread: Boolean get() = Looper.getMainLooper() ""=== Looper.myLooper()
  4. expect/actual mechanism "// In common code expect val isMainThread: Boolean

    "// In Android/JVM actual val isMainThread: Boolean get() = Looper.getMainLooper() ""=== Looper.myLooper() "// In iOS/Native actual val isMainThread: Boolean get() = NSThread.isMainThread()
  5. SQLDelight SQLDelight generates typesafe APIs from SQL statements and verifies

    at compile-time the schemas, statements, migrations, and so on.
  6. SQLDelight SQLDelight generates typesafe APIs from SQL statements and verifies

    at compile-time the schemas, statements, migrations, and so on. It also provides IDE features like autocomplete.
  7. SQLDelight SQLDelight generates typesafe APIs from SQL statements and verifies

    at compile-time the schemas, statements, migrations, and so on. It also provides IDE features like autocomplete. SQLDelight currently supports the SQLite dialect, and there are supported drivers for Android, JVM, iOS and Windows.
  8. SQLDelight • SQL is standardized. • Everyone understands SQL. •

    It’s not required to learn a custom DSL of an ORM library.
  9. SQLDelight • SQL is standardized. • Everyone understands SQL. •

    It’s not required to learn a custom DSL of an ORM library. • You write SQL code and let SQLDelight generates Kotlin code.
  10. SQLDelight • Write SQL into .sq files • Build the

    project • Use generated code! • Migrate you database writing code into .sqm files
  11. SQLDelight dependencies { classpath("com.squareup.sqldelight:gradle-plugin:1.3.0") } plugins { id("com.squareup.sqldelight") } sqldelight

    { database(name = "TodoAppDatabase") { packageName = "io.github.wellingtoncosta.todoapp" } }
  12. SQLDelight 
 // For Android target
 implementation("com.squareup.sqldelight:android-driver:1.3.0") // For iOS

    target implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core-native:1.3.7")
  13. SQLDelight // Todo.sq file
 CREATE TABLE todos ( id INTEGER

    NOT NULL PRIMARY KEY AUTOINCREMENT, external_id TEXT UNIQUE DEFAULT NULL, title TEXT NOT NULL, description TEXT, status TEXT AS TodoStatus NOT NULL );
  14. SQLDelight // Todo.sq file
 selectAll: SELECT * FROM todos; selectByExternalId:

    SELECT * FROM todos WHERE external_id = ?; insert: INSERT INTO todos (external_id, title, description, status) VALUES (?,?,?,?); updateStatus: UPDATE todos SET status = ? WHERE id = ?;
  15. Ktor Ktor is an open source project sponsored by Jetbrains

    for building backend applications. It also has a HTTP client that supports several platforms using Kotlin Multiplatform.
  16. Ktor Ktor is an open source project sponsored by Jetbrains

    for building backend applications. It also has a HTTP client that supports several platforms using Kotlin Multiplatform. Currently, the supported platforms are Android, JVM, iOS, JS and native.
  17. Ktor 
 // For common module
 implementation(“io.ktor:ktor-client-core:1.3.2”) // For Android

    target implementation(“io.ktor:ktor-client-android:1.3.2”) // For iOS target implementation(“io.ktor:ktor-client-ios:1.3.2”)
  18. Ktor // Common code expect val engine: HttpClientEngineFactory<HttpClientEngineConfig> val client

    = HttpClient(engine) { install(JsonFeature) { serializer = KotlinxSerializer(json) } }
  19. Ktor // Common code expect val engine: HttpClientEngineFactory<HttpClientEngineConfig> val client

    = HttpClient(engine) { install(JsonFeature) { serializer = KotlinxSerializer(json) } install(Logging) { logger = Logger.SIMPLE level = LogLevel.ALL } … }
  20. Ktor // Common code suspend fun getAll(): List<TodoResponse> { return

    client.get { url { path("todos") } } } suspend fun save(request: SaveTodoRequest): TodoResponse { return client.post { url { path("todos") } header(HttpHeaders.ContentType, ContentType.Application.Json) body = request } }
  21. Kotlin Serialization dependencies { classpath("org.jetbrains.kotlin:kotlin-serialization:1.3.72") } // Common code implementation(“org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:0.20.0")

    // Android target implementation(“org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") // iOS target implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:0.20.0")
  22. Kotlin Serialization @Serializable data class TodoResponse( val id: String, val

    title: String, val description: String? = null, val status: TodoStatus )
  23. Kotlin Serialization @Serializable data class TodoResponse( val id: String, val

    title: String, val description: String? = null, val status: TodoStatus ) @Serializable data class SaveTodoRequest( val title: String, val description: String?, val status: TodoStatus )
  24. • SQLDelight • Ktor • Kotlin Serialization • Kotlin Coroutines

    • Kotlin/Native Cocoapod plugin Weapons starter pack
  25. Kotlin/Native Cocoapod plugin plugins { id("org.jetbrains.kotlin.native.cocoapods") } cocoapods { authors

    = "Wellington Costa Pereira" license = "MIT" summary = "Common core for Todo App." homepage = "https://github.com/wellingtoncosta/todo-app-kotlin-multiplatform" }
  26. Kotlin/Native Cocoapod plugin Pod::Spec.new do |spec| spec.name = 'shared' spec.version

    = '1.0' spec.homepage = 'https://github.com/wellingtoncosta/todo-app-kotlin-multiplatform' spec.source = { :git => "Not Published", :tag => "Cocoapods/#{spec.name}/#{spec.version}" } spec.authors = 'Wellington Costa Pereira' spec.license = 'MIT' spec.summary = 'Common core for Todo App.' spec.static_framework = true spec.vendored_frameworks = "build/cocoapods/framework/shared.framework" spec.libraries = "c++" spec.module_name = "#{spec.name}_umbrella" spec.pod_target_xcconfig = { 'KOTLIN_TARGET[sdk=iphonesimulator*]' => 'ios_x64', 'KOTLIN_TARGET[sdk=iphoneos*]' => 'ios_arm', 'KOTLIN_TARGET[sdk=watchsimulator*]' => 'watchos_x86', 'KOTLIN_TARGET[sdk=watchos*]' => 'watchos_arm', 'KOTLIN_TARGET[sdk=appletvsimulator*]' => 'tvos_x64', 'KOTLIN_TARGET[sdk=appletvos*]' => 'tvos_arm64', 'KOTLIN_TARGET[sdk=macosx*]' => 'macos_x64' } spec.script_phases = [ { :name => 'Build shared', :execution_position => :before_compile, :shell_path => '/bin/sh', :script => <<-SCRIPT set -ev REPO_ROOT="$PODS_TARGET_SRCROOT" "$REPO_ROOT/../gradlew" -p "$REPO_ROOT" :shared:syncFramework \ -Pkotlin.native.cocoapods.target=$KOTLIN_TARGET \ -Pkotlin.native.cocoapods.configuration=$CONFIGURATION \ -Pkotlin.native.cocoapods.cflags="$OTHER_CFLAGS" \ -Pkotlin.native.cocoapods.paths.headers="$HEADER_SEARCH_PATHS" \ -Pkotlin.native.cocoapods.paths.frameworks="$FRAMEWORK_SEARCH_PATHS" SCRIPT } ] end
  27. Kotlin/Native Cocoapod plugin target 'TodoApp' do # Comment the next

    line if you don't want to use dynamic frameworks use_frameworks! # Pods for TodoApp pod 'SnapKit', '~> 5.0.1' pod 'shared', :path => '../shared' target 'TodoAppTests' do inherit! :search_paths # Pods for testing end target 'TodoAppUITests' do # Pods for testing end end
  28. Kotlin/Native Cocoapod plugin target 'TodoApp' do # Comment the next

    line if you don't want to use dynamic frameworks use_frameworks! # Pods for TodoApp pod 'SnapKit', '~> 5.0.1' pod 'shared', :path => '../shared' target 'TodoAppTests' do inherit! :search_paths # Pods for testing end target 'TodoAppUITests' do # Pods for testing end end