Skip to content

Kotlin Multiplatform

Ruby Lichtenshtein edited this page Nov 4, 2018 · 8 revisions

Kotlin Multiplatform

Multiplatform projects are an experimental feature in Kotlin 1.2 and 1.3. All of the language and tooling features described in this document are subject to change in future Kotlin versions.

 

sharing code between platforms. With support for JVM, Android, JavaScript, iOS, Linux, Windows, Mac and even embedded systems like STM32, 

How it works

Overall, multiplatform is not about compiling all code for all platforms. This model has its obvious limitations, and we understand that modern applications need access to unique features of the platforms they are running on. Kotlin doesn't limit you to the common subset of all APIs in the world. Every component can share as much code as needed with others but can access platform APIs at any time through the expect/actual mechanism provided by the language.

Platform-Specific Declarations - expected/actual mechanism

Example
enum class LogLevel {
    DEBUG, WARN, ERROR
}

expect fun writeLogMessage(message: String, logLevel: LogLevel)

fun logDebug(message: String) = writeLogMessage(message, LogLevel.DEBUG)
fun logWarn(message: String) = writeLogMessage(message, LogLevel.WARN)
fun logError(message: String) = writeLogMessage(message, LogLevel.ERROR)

On the JVM

actual fun writeLogMessage(message: String, logLevel: LogLevel) {
    println("[$logLevel]: $message")
}

In the JavaScript world

actual fun writeLogMessage(message: String, logLevel: LogLevel) {
    when (logLevel) {
        LogLevel.DEBUG -> console.log(message)
        LogLevel.WARN -> console.warn(message)
        LogLevel.ERROR -> console.error(message)
    }
}
Why not interfaces?
  • All implementations are known at compile time.
  • Simpler implementation - no factory or DI.
  • Interface dose not have contractors.
  • Top level and extension functions.

Interface dose not have contractors.

expect abstract class BaseRepo<T>(
    val ref: String,
    val parser: Parser<T>
) {
    suspend fun get(id: String): T
}

Android Actual

import com.google.firebase.firestore.FirebaseFirestore

actual abstract class BaseRepo<T> actual constructor(
    val ref: String,
    val parser: Parser<T>
) {
    val collection = FirebaseFirestore.getInstance().collection(ref)

    actual suspend fun get(id: String): T {
        val documentSnapshot = collection
            .document(id)
            .get()
            .await()

        return parser.parse(documentSnapshot)
    }
}

Js Actual

import kotlinx.coroutines.await
import rubylich.ktmp.functions.ts2kt_firebase_admin.Firestore

actual abstract class BaseRepo<T> actual constructor(
    val ref: String,
    val parser: Parser<T>
) {
    val collection = Firestore().collection(ref)

    actual suspend fun get(id: String): T {
        val documentSnapshot = collection.doc(id).get().await()
        return parser.parse(documentSnapshot)
    }
}

Top level and extension functions.

//common
expect fun <T> T.printMe()

//JVM
actual fun <T> T.printMe() = print(this)

//Js
actual fun <T> T.printMe() = console.log(this)
Common module.
  • Cannot referance any platform spsific code.
  • Can only have kotlin code.
  • Can only depend on other Kotlin common module or libraris.

Multiplatform Architecture.

Clients Architecture.

  • Data Models.
  • Repositores.
  • Presenters.
  • Views.

arch_client

Server Architecture.

  • Data Models.
  • Repositores.
  • Apis.

arch_backend

Arch all.

arch_all