Loading

Kotlin 1.6 Multiplatform

Tobse Fritz

This is a live streamed presentation. You will automatically follow the presenter and see the slide they're currently on.

Kotlin Multiplatform

JVM

Android

Browser

Native

Kotlin 1.6

Tobse Fritz

  •       Reich
  •       Gut aussehend
     
  •       ITscope GmbH
  •       Kotlin Fanboy
  •        Java Entwickler
  •       Clean Coder  
  •       Hobby Fotograf
  •       Gaming Nerd  
  •       3D Printer
  •       Daddy

Tobse Fritz

GitHub

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

BackEndHills

DesktopCountry

VeganGrounds

MobileRivers

CloudMountains

ConfigIsland

FrontendArea

NativeGrounds

Und wo wohnst DU?

https://www.menti.com
Code: 1842 9218

Kotlin Features

  • Prägnant
  • Sicher
  • Interoperabel
  • Optimales Tooling

Kotlin Features

public class Person {

    private final String firstName;
    private final String lastName;
    private final LocalDate birthDay;

    public Person(String firstName, String lastName, 
                  LocalDate birthDay) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.birthDay = birthDay;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public LocalDate getBirthDay() {
        return birthDay;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(firstName, person.firstName) &&
                Objects.equals(lastName, person.lastName) &&
                Objects.equals(birthDay, person.birthDay);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstName, lastName, birthDay);
    }

    @Override
    public String toString() {
        return "Person{" +
                "firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", birthDay=" + birthDay +
                '}';
    }
}
data class PersonK(
    val firstName: String,
    val lastName: String,
    val birthDay: LocalDate
)

Java

Kotlin

Prägnanz

Kotlin Features

Sicher

var name: String
name = null
println(name.length)

Kotlin

// Compile Error 🤗
⚡NullpointerException 🤔
var name: String?
name = null
if(name != null){
  println(name.length)
}

Kotlin Features

Sicher

var output: String
output = null

Kotlin

val name: String? = null
println(name.length)
fun calculateTotal(obj: Any) {
    if (obj is Invoice){
        obj.calculateTotal()
    }
}
fun isCloneBaby(father: Person, son: Person): Boolean {
    return father == son
}
// Compile Error
// Compile Error
// Autocast
// equals()

Kotlin Features

Interoperabel

fun callJava(){
  val backend = LegacyBackend()
  backend.sendMail("Be prepared... we deploy")
}

Kotlin

private void callKotlin(){
  var backend = new NewBackend();
  backend.sendSlack("We introduced NetID oAuth!");
}

Java

Kotlin Features

Interoperabel

  • iOS (arm32, arm64, simulator x86_64)
  • MacOS (x86_64)
  • Android (arm32, arm64)
  • Windows (mingw x86_64, x86)
  • Linux (x86_64, arm32, MIPS, MIPS little endian, Raspberry Pi)
  • WebAssembly (wasm32)

Kotlin Features

Optimales Tooling

Kotlin Features

  • Prägnant
  • Sicher
  • Interoperabel
  • Optimales Tooling
  • Frei & OpenSource

Kotlin Features

  • Prägnant
  • Sicher
  • Interoperabel
  • Optimales Tooling

Kotlin Features

Prägnant

Sicher

Interoperabel

Optimales Tooling

Frei & OpenSource

Inline Classes

Extensions

Delegtions

String Builders

Contracts

Operator Overloading

Gradle DSL

Data Classes

Coroutines

Kotlin Everywhere

Trello

Evernote

Trivago

Runtastic

Tinder

Uber

My Taxi

Klarna

Mastercard

N26

182 %
Wachstum auf GitHub 2019

Wer hat's erfunden?

Jul  2011  - Öffentliche Bekanntmachung

Feb 2016 - Release Version 1.0

Nov 2017 - Release Version 1.2

Mai 2017 - Offizielle Sprache für Android

Kotlin Native v0.4 & Multiplatform

Okt 2018 - Gründung Kotlin Foundation

Wer hat's erfunden?

Jul  2011  - Öffentliche Bekanntmachung

Feb 2016 - Release Version 1.0

Nov 2017 - Release Version 1.2

Mai 2017 - Offizielle Sprache für Android

Kotlin Native v0.4 & Multiplatform

Okt 2018 - Gründung Kotlin Foundation

Aug 2020 - Kotlin Multiplatform Mobile - Alpha

Nov 2020 - Jetpack Compose for Desktop - M1

Mai 2021 - Jetpack Compose for Web

Nov 2021 - Release Kotlin 1.6

Dez 2021 - Compose Multiplatform  1.0

Wer hat's erfunden?

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin JVM

Kotlin
Compiler

Java
Compiler

Kotlin

Runtime

*.kt
*.class
*.java
*.jar

Interoperabel

fun callJava(){
  val backend = LegacyBackend()
  backend.sendMail("Be prepared... we deploy")
}

Kotlin

private void callKotlin(){
  var backend = new NewBackend();
  backend.sendSlack("We introduced NetID oAuth!");
}

Java

Kotlin JVM

Kotlin JVM

Kotlin JVM

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String handle() {
        return "Hello WebFlux";
    }
}

Spring WebFlux provides an annotation-based programming model, where @Controller and @RestController components use annotations to express request mappings, request input, handle exceptions, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.

The following listing shows a basic example:

https://docs.spring.io/spring/docs/.../web-reactive.html

Kotlin

Java

Kotlin JVM

@RestController
class HelloController {

    @GetMapping("/hello")
    fun handle() = "Hello WebFlux"
}

Spring WebFlux provides an annotation-based programming model, where @Controller and @RestController components use annotations to express request mappings, request input, handle exceptions, and more. Annotated controllers have flexible method signatures and do not have to extend base classes nor implement specific interfaces.

The following listing shows a basic example:

https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html

https://docs.spring.io/spring/docs/.../web-reactive.html

Kotlin

Java

Kotlin

Java

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin Gradle DSL

plugins {
    kotlin("jvm") version "1.5"
    java
}

group = "de.tfr.presentation"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    implementation(kotlin("stdlib-js"))
    testCompile("junit", "junit", "4.12")
}

configure<JavaPluginConvention> {
    languageVersion.set(JavaLanguageVersion.of(11))
}

Kotlin Gradle DSL

Example 1. Dependency declarations for a JVM-based project

Groovy

Kotlin

plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.hibernate:hibernate-core:3.6.7.Final'
    api 'com.google.guava:guava:23.0'
    testImplementation 'junit:junit:4.+'
}

Kotlin Gradle DSL

Example 1. Dependency declarations for a JVM-based project

Groovy

Kotlin

plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.hibernate:hibernate-core:3.6.7.Final")
    api("com.google.guava:guava:23.0")
    testImplementation("junit:junit:4.+")
}

Kotlin Scratch Files

fun ourCoolBuildScript(){
    val timeStamp = LocalDateTime.now()
    downloadI18nMessages()
    formatMessageProperties()
    mergeChangeLogEntries(timeStamp)
    sendSlackMessage("We're gonna deploy that stuff 🤘")
}

One-Click Scripts

*.kts

Kotlin Scratch Files

  • Build scripts (Gradle/Kobalt)
  • Test scripts (Spek)
  • Command-line Utilities
  • Routing Skripte (ktor)
  • Type-safe configuration files (TeamCity)
  • In-process scripting and REPL for IDE
  • Consoles like IPython/Jupyter Notebook
  • Game scripting engines

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Welcome
to the Native World

Kotlin Native

Kotlin Native

Kotlin Multiplatform

!=

Kotlin Native

Technologie um Kotlin Code zu nativen Binaries zu kompilieren, die ohne VM laufen.

  • Bestmögliche Integration in existierende Systeme
  • Einfache Anwendung
  • Nützliches Tooling

Kotlin Native

  • iOS (arm32, arm64, simulator x86_64)
  • MacOS (x86_64)
  • Android (arm32, arm64)
  • Windows (mingw x86_64, x86)
  • Linux (x86_64, arm32, MIPS, MIPS little endian, Raspberry Pi)
  • WebAssembly (wasm32)

JVM

Android

Browser

Native

Kotlin Native

Kotlin
Compiler

LLVM
Compiler

*.kt
LLVM IR
*.exe

The LLVM Compiler Infrastructure.
IR =
 Intermediate Representation 

Kotlin Native

Kotlin
Compiler

Kotlin
Compiler

*.kt
LLVM IR
*.exe

The LLVM Compiler Infrastructure.
IR =
 Intermediate Representation 

Frontend

Backend

Kotlin Native

val appData = SystemUtil.getEnvironmentVariable("LOCALAPPDATA")
val toolboxPath = """$appData\JetBrains\Toolbox"""
val channelsPath = """$toolboxPath\apps\IDEA-U\ch-0\"""


fun main(args: Array<String>) {
    runIntelliJ(getProjectPath(args))
}

fun runIntelliJ(projectPath: String?) {
    File(path = channelsPath)
        .listAllFolders()
        .filter(::isVersion)
        .mapToVersion()
        .findNewestVersion()
        ?.getIntellIJPath()
        ?.exec(params  = projectPath)
}

Kotlin Native

import kotlinx.cinterop.alloc
import kotlinx.cinterop.nativeHeap
import kotlinx.cinterop.ptr
import kotlinx.cinterop.toKString
import platform.windows.*

data class File(val fileName: String? = null, val path: String, val type: Type) {

  enum class Type { File, Folder, Unknown }

  fun listAllFiles(): List<File> {
    val searchPath = "$path*".replace("/", "\\")
    val files = mutableListOf<File>()
    val fileData = nativeHeap.alloc<_WIN32_FIND_DATAA>()
    val handle: HANDLE? = FindFirstFileA(searchPath, fileData.ptr)
    var fileNumber = 0
    val maxFilesToScan = 1000
    if (handle != INVALID_HANDLE_VALUE) {
      do {
        val fileName = fileData.cFileName.toKString()
        var type = Type.Unknown
        if (fileData.dwFileAttributes.toInt() and FILE_ATTRIBUTE_NORMAL > 0) {
          type = Type.File
        }
        if (fileData.dwFileAttributes.toInt() and FILE_ATTRIBUTE_DIRECTORY > 0) {
          type = Type.Folder
        }
        files += File(fileName = fileName, path = path, type = type)
        fileNumber++
      } while (FindNextFileA(handle, fileData.ptr) != 0 
                && fileNumber < maxFilesToScan)
      FindClose(handle)
    } else {
      println("Illegal Path")
    }
    return files
  }

  fun exec(params: String? = "") {
    val command = "${toAbsolutePath()} ${params ?: ""}"
    WinExec(command, SW_SHOW)
  }

  fun toAbsolutePath(): String {
    return path + fileName
  }

  fun listAllFolders(): List<File> {
    return listAllFiles().filter { file -> file.type == Type.Folder }
  }

  fun isFolder() = type == Type.Folder

  override fun toString() = "$type:${toAbsolutePath()}"
}

Kotlin Native

Kotlin Native

Wie schnell ist das denn?

Wie schnell ist das denn?

fun main(args: Array<String>) {

    val start =  getTimeMillis()

    var c = 0L
    var string = ""
    for(i in 0.. 100_000){
        c += (i / 2)
        c += 1
        string += c
    }

    println( getTimeMillis() - start)
}

BENCHMARK

Benchmark

[ millisekunden / run ]   weniger ist besser

IT DEPENDS

Source Code

Runtime

VM

Graal

VM

Graal

JVM
Java 15

JVM
Java 15

Math

String

Memory

Math

String

Memory

Chromium

Native Win x64

Kotlin 1.5

image/svg+xml

Kotlin 1.4

image/svg+xml

Compiler

fun benchMath(iterations: Int): Double {
  var c = 0.0
  for (i in 0..iterations) {
    c += (i / 2.0)
    c += (i % 3.0)
    c += sqrt(i * 3.0)
    c += 1
  }
  return c
}

Math Benchmark

100_000_000

fun benchString(iterations: Int) {
  var c = 0L
  var string = ""
  for (i in 0..iterations) {
    c += (i / 3)
    c += 1
    val next = c % 10
    string += next
  }
}

String Benchmark

100_000

fun benchObjectList(iterations: Int): Int {
  val list = mutableListOf<Machine>()
  for (i in 0..iterations) {
  	list.add(Machine("ABC-0$i", i, i / 3.0))
  }
  return list.size
}

class Machine(val name: String, val wheels: Int, val weight: Double)

Memory Benchmark

10_000_000

void benchMath(int iterations) {
  var c = 0.0;
  for (int i =0; i < iterations; i++) {
    c += (i / 2.0);
    c += (i % 3.0);
    c += Math.sqrt(i * 3.0);
    c += 1;
  }
}

Math Benchmark

100_000_000

void benchString(int iterations) {
  var c = 0;
  var string = "";
  for (int i = 0; i < iterations; i++) {
    c += (i / 3);
    c += 1;
    var next = c % 10;
    string += next;
  }
}

String Benchmark

100_000

Math Benchmark

100_000_000

public class BenchmarkMemory {

  void benchObjectList(int iterations) {
    var list = new ArrayList<PerpetuumMobile>();
    for (int i = 0; i < iterations; i++) {
    	list.add(new PerpetuumMobile("ABC-0" + i, i, (i / 3.0)));
    }
  }

  private static class Machine {
    String name;
    Integer wheels;
    Double weight;

    public Machine(String name, int wheels, double weight) {
      this.name = name;
      this.wheels = wheels;
      this.weight = weight;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Machine that = (Machine) o;
      return wheels == that.wheels && Double.compare(that.weight, weight) 
      == 0 && Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {
    	return Objects.hash(name, wheels, weight);
    }

  }
}
Chrome Headless 90.4430.93
Open JDK 15.0.2
GraalVM Native-Image 21.0.0.2
Windows 10 x64 AMD Ryzen 7 1800X
64GB RAM

Messungen

Multiplatform Benchmark

Multiplatform Benchmark

Benchmark

Benchmark

Benchmark

Benchmark

Und der Speicher?
Und der Speicher?
Und der Speicher?

Memory Benchmark 10_000_000

Und der Speicher?
Und der Speicher?
Wie groß ist es?
Wie groß ist es?
Wie groß ist es?

Kotlin Native Hallo World 

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin Native

vs

Graal

VM

Graal

VM

Language Choice

High Performance

Advanced Tools

Ahead-of-Time Compilation

Startup Time

Memory Footprint

Graal

VM

Graal

VM

Kotlin Native Graal VM
Fokus Interoperabilität Polyglot + Performance
Sprache Kotlin 1.6 Java 17, R, JS, Python 
Status Beta 21.3
Platform Win, Linux, Mac, IOS, Android, Embedded Linux, Mac, (Win)
Lizenz Apache License 2.0 GPL - Community  Ed.

Kotlin Native

vs

Kotless

kotless {
  config {

      aws {
        storage {
            bucket = "kotless.s3.example.com"
      }

      profile = "example"
      region = "eu-west-1"
    }
  }

  webapp {
  	dns("kotless", "example.com")
  }
}

Kotlin serverless framework

settings.gradle.kts:

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin JS

Kotlin
Transpiler

*.kt
*.ts
*.js
*.map

Kotlin JS

Kotlin JS

[
  {
    "title": "Temtem",
    "price": "39,99 €",
    "description": "Temtem ist ein Multiplayer-Kreaturen-Sammlung Abenteuer, 
                    inspiriert von Pokémon.",
    "url": "https://store.steampowered.com/app/745920/Temtem/",
    "coverUrl": "https://steamcdn-a.akamaihd.net/steam/apps/745920/header.jpg"
  },
  {
    "title": "A Plague Tale: Innocence",
    "price": "39,99 €",
    "description": "Folge den Spuren von Hugo [..]",
    "url": "https://store.steampowered.com/app/752590/A_Plague_Tale_Innocence/",
    "coverUrl": "https://steamcdn-a.akamaihd.net/steam/apps/752590/header.jpg"
  }
]
game_wishlist.json

Kotlin JS

plugins {
    id("kotlin2js") version "1.6.10"
}

dependencies {
    implementation(kotlin("stdlib-js"))
}
build.gradle.kts
<html>
  <body>
  <!-- Link to the compiled js files-->
  <script src="kotlin.js"></script>
  <!-- Link to the compiled js files-->
  <script src="output.js"></script>

  </body>
</html>
index.html

Kotlin JS

import kotlinx.browser.document
import kotlinx.browser.window
import kotlinx.dom.addClass
import org.w3c.dom.Element
import org.w3c.dom.HTMLButtonElement
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLImageElement

fun build(game: Game): Element {
  val containerElement = document.createElement("div") as HTMLDivElement
  val imageElement = document.createElement("img") as HTMLImageElement
  val titleElement = document.createElement("div") as HTMLDivElement
  val priceElement = document.createElement("div") as HTMLDivElement
  val descriptionElement = document.createElement("div") as HTMLDivElement
}
data class Game(val title: String, val price: String, val description: String, val url: String, val coverUrl: String)

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin Android

Kotlin
Compiler

Java
Compiler

*.kt
*.class
*.java

JVM
Java Virtual Machine

Kotlin Android

Kotlin
Compiler

Java
Compiler

*.kt
*.class
*.java

DEX
Compiler

DVM
Dalvik Virtual Machine

Kotlin Android

Kotlin
Compiler

Java
Compiler

*.kt
*.class
*.java

DEX
Compiler

ART
Android Runtime

AOT
Compiler

Kotlin Android

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Kotlin Multiplatform

Technologie um Kotlin Code auf unterschiedlichen Plattformen
wiederzuverwenden.

  • Interoperabilität
  • Maximale Code Wiederverwendung
    • Über ein Kotlin Common Modul

Kotlin Multiplatform

  • Kann sich ändern
  • Offizielle Doku ist Referenz

Kotlin Multiplatform

Kotlin 1.3

JVM

image/svg+xml

JS

Linux

macOS

Common

Kotlin Multiplatform

JVM

image/svg+xml

JS

Linux

macOS

Common

Native

JVM + JS

Kotlin Multiplatform

JVM

JS

Linux

macOS

Common

Native

JVM + JS

Kotlin Multiplatform

JVM

JS

Linux

macOS

Common

Native

JVM + JS

Kotlin Multiplatform

JVM

JS

Linux

macOS

Common

Native

JVM + JS

Kotlin Multiplatform

*.kt

Kotlin
Compiler

image/svg+xml

Kotlin
Compiler

image/svg+xml

Kotlin
Compiler

image/svg+xml
*.js
*.class
*.kt
*.kt

Kotlin 1.4

*.exe

Kotlin
Compiler

Backend

LLVM IR

Kotlin Multiplatform

Kotlin
Compiler

image/svg+xml
*.kt

Kotlin
Compiler

image/svg+xml

Kotlin
Compiler

image/svg+xml

Kotlin
Compiler

image/svg+xml
*.js
*.class
*.kt
*.kt
LLVM IR

Kotlin 1.5

*.exe

Backend

Frontend

JVM

image/svg+xml

JS

Linux

IOS

Common

Kotlin Multiplatform

Android

Dependency Management

JVM

image/svg+xml

JS

Linux

IOS

Common

Kotlin Multiplatform

Android

Dependency Management

JVM

image/svg+xml

Common-Date-Util-Lib

JVM

image/svg+xml

JS

Linux

IOS

Common

Kotlin Multiplatform

Android

Dependency Management

Mobile-DB-OR-Mapper-Lib

Android

JVM

image/svg+xml

JS

Linux

IOS

Common

Kotlin Multiplatform

Android

Dependency Management

Twitter-Rest-API

JS

Kotlin Multiplatform

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

Common

internal actual fun writeLogMessage(message: String, logLevel: LogLevel) {
    when (logLevel) {
        LogLevel.DEBUG -> console.log(message)
        LogLevel.WARN -> console.warn(message)
        LogLevel.ERROR -> console.error(message)
    }
}
expect
actual

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Multiplatform

Mobile

Kotlin

Multiplatform

Mobile

Kotlin

Multiplatform

Mobile

Kotlin

  • DRY
  • Bestpractise und Architektur der
    Platform beibehalten
  • Nativ = Keine Crossplatform Technologie
  • Keine Änderung für Android
  • Für IOS ist es nur ein Library import
  • Nur die UI-Layer wird doppelt geschrieben

Kotlin Everywhere

https://kotlinlang.org/lp/mobile/case-studies/

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

DevLand

VeganCountry

MobileRivers

CloudMountains

NativeIsland

FrontendArea

ConfigHills

BackEndGrounds

Jetpack Compose

Jetpack Compose

For
Android

For
Desktop

For
 Web

Nov 2020

TECHNICAL
PREVIEW

Mai 2021

TECHNICAL
PREVIEW

STABLE

Jul 2021 

Jetpack Compose

@Composable
fun App() {
  MaterialTheme {
    Button(){
      Text("Hallo World")
    }
  }
}
  • Funktional
    • Stateless
    • Keine Seiteneffekte
    • Idempotent
    • Kein return
  • Deklarativ
  • Reaktiv
  • UI in Code

f(   )

Data

UI

Jetpack Compose

@Composable
fun App() {
  MaterialTheme {
    halloButton("Hallo World")
  }
}

@Composable
private fun halloButton(text: String) {
  Button() {
    Text(text)
  }
}

f(   )

Data

UI

Jetpack Compose

@Composable
fun App() {
  MaterialTheme {
    halloButton("Hallo World")
  }
}

@Composable
private fun halloButton(text: String) {
  var textProperty by remember { mutableStateOf(text) }
  Button( onClick = { text += " - Live in Peace" }) {
    Text(textProperty)
  }
}

Jetpack Compose

@Composable
private fun halloButton(text: String) {

Kotlin Compiler

Compose Compiler Plugin

Kotlin Multiplatform

Kotlin JVM

Kotlin Native

Kotlin JS

Desktop

IOS

JAR