遇见 Kotlin

Bennyhuo

个人介绍

霍丙乾 Bennyhuo

  • 腾讯地图 Android 工程师
  • Kotlin “布道师”
  • Kotlin 微信公众号
  • 目前国内第一套 Kotlin 视频教程

最新视频:Kotlin 入门到进阶

http://coding.imooc.com/class/108.html

Kotlin 是什么

Kotlin 官网

静态语言

  • 与 Java 完美兼容
  • 有完美的 IDE 提示
  • 确定的类型给人以安全感
import kotlin.browser.document

/**
 * Created by benny on 4/30/17.
 */

fun main(args: Array<String>) {
    document.writeln("Hello World from Kotlin-js")
}

Observable
    .from("HelloWorld".toCharArray().asIterable())
    .zipWith(
            Observable.interval(1, 1, TimeUnit.SECONDS), 
            { a, b -> "$a, $b" })
    .subscribe(::println)

可以跑在Java 虚拟机上


Observable
    .from("HelloWorld".toCharArray().asIterable())
    .zipWith(
            Observable.interval(1, 1, TimeUnit.SECONDS), 
            { a, b -> "$a, $b" })
    .subscribe(::println)
// ================net/println/kt07/LambdaKt.class =================
// class version 50.0 (50)
// access flags 0x31
public final class net/println/kt07/LambdaKt {


  // access flags 0x19
  public final static main([Ljava/lang/String;)V
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
   L0
    ALOAD 0
    LDC "args"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L1
    LINENUMBER 16 L1
   L2
    LINENUMBER 20 L2
   L3
    LINENUMBER 16 L3
   L4
    LINENUMBER 17 L4
   L5
    LINENUMBER 16 L5
    LDC "HelloWorld"
    ASTORE 1
   L6
    ALOAD 1
   L7
    INVOKEVIRTUAL java/lang/String.toCharArray ()[C
    DUP
    LDC "(this as java.lang.String).toCharArray()"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
   L8
   L9
    LINENUMBER 16 L9
    INVOKESTATIC kotlin/collections/ArraysKt.asIterable ([C)Ljava/lang/Iterable;
    INVOKESTATIC rx/Observable.from (Ljava/lang/Iterable;)Lrx/Observable;
    LCONST_1
    LCONST_1
    GETSTATIC java/util/concurrent/TimeUnit.SECONDS : Ljava/util/concurrent/TimeUnit;
    INVOKESTATIC rx/Observable.interval (JJLjava/util/concurrent/TimeUnit;)Lrx/Observable;
    GETSTATIC net/println/kt07/LambdaKt$main$1.INSTANCE : Lnet/println/kt07/LambdaKt$main$1;
    CHECKCAST rx/functions/Func2
   L10
    LINENUMBER 17 L10
    INVOKEVIRTUAL rx/Observable.zipWith (Lrx/Observable;Lrx/functions/Func2;)Lrx/Observable;
    NEW net/println/kt07/LambdaKt$sam$Action1$75bbf535
    DUP
    GETSTATIC net/println/kt07/LambdaKt$main$2.INSTANCE : Lnet/println/kt07/LambdaKt$main$2;
    CHECKCAST kotlin/jvm/functions/Function1
    DUP
    IFNONNULL L11
    POP
    POP2
    ACONST_NULL
    GOTO L12
   L11
    INVOKESPECIAL net/println/kt07/LambdaKt$sam$Action1$75bbf535.<init> (Lkotlin/jvm/functions/Function1;)V
   L12
    CHECKCAST rx/functions/Action1
   L13
    LINENUMBER 20 L13
    INVOKEVIRTUAL rx/Observable.subscribe (Lrx/functions/Action1;)Lrx/Subscription;
    POP
   L14
    LINENUMBER 22 L14
    LDC 15000
    INVOKESTATIC java/lang/Thread.sleep (J)V
   L15
    LINENUMBER 23 L15
    RETURN
   L16
    LOCALVARIABLE args [Ljava/lang/String; L0 L16 0
    MAXSTACK = 6
    MAXLOCALS = 2

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=2, d1={"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0011\n\u0002\u0010\u000e\n\u0002\u0008\u0002\u001a\u0019\u0010\u0000\u001a\u00020\u00012\u000c\u0010\u0002\u001a\u0008\u0012\u0004\u0012\u00020\u00040\u0003\u00a2\u0006\u0002\u0010\u0005\u00a8\u0006\u0006"}, d2={"main", "", "args", "", "", "([Ljava/lang/String;)V", "production sources for module kt07_main"})
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$1 null null
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$2 null null
  // compiled from: Lambda.kt
  // debug info: SMAP
Lambda.kt
Kotlin
*S Kotlin
*F
+ 1 Lambda.kt
net/println/kt07/LambdaKt
*L
1#1,28:1
*E

}


// ================net/println/kt07/LambdaKt$main$1.class =================
// class version 50.0 (50)
// access flags 0x30
// signature <T1:Ljava/lang/Object;T2:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;Lrx/functions/Func2<TT;TT2;TR;>;
// declaration: net/println/kt07/LambdaKt$main$1<T1, T2, R> implements rx.functions.Func2<T, T2, R>
final class net/println/kt07/LambdaKt$main$1 implements rx/functions/Func2  {


  // access flags 0x1041
  public synthetic bridge call(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
    ALOAD 0
    ALOAD 1
    CHECKCAST java/lang/Character
    ALOAD 2
    CHECKCAST java/lang/Long
    INVOKEVIRTUAL net/println/kt07/LambdaKt$main$1.call (Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;
    ARETURN
    MAXSTACK = 3
    MAXLOCALS = 3

  // access flags 0x11
  public final call(Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;
  @Lorg/jetbrains/annotations/NotNull;() // invisible
   L0
    LINENUMBER 19 L0
    NEW java/lang/StringBuilder
    DUP
    INVOKESPECIAL java/lang/StringBuilder.<init> ()V
    ALOAD 1
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    LDC ", "
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/Object;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
   L1
    ARETURN
   L2
    LOCALVARIABLE this Lnet/println/kt07/LambdaKt$main$1; L0 L2 0
    LOCALVARIABLE a Ljava/lang/Character; L0 L2 1
    LOCALVARIABLE b Ljava/lang/Long; L0 L2 2
    MAXSTACK = 2
    MAXLOCALS = 3

  // access flags 0x0
  <init>()V
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x19
  public final static Lnet/println/kt07/LambdaKt$main$1; INSTANCE

  // access flags 0x8
  static <clinit>()V
    NEW net/println/kt07/LambdaKt$main$1
    DUP
    INVOKESPECIAL net/println/kt07/LambdaKt$main$1.<init> ()V
    PUTSTATIC net/println/kt07/LambdaKt$main$1.INSTANCE : Lnet/println/kt07/LambdaKt$main$1;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3, d1={"\u0000\u0018\n\u0000\n\u0002\u0010\u000e\n\u0000\n\u0002\u0010\u000c\n\u0002\u0008\u0002\n\u0002\u0010\u0009\n\u0002\u0008\u0002\u0010\u0000\u001a\u00020\u00012\u000e\u0010\u0002\u001a\n \u0004*\u0004\u0018\u00010\u00030\u00032\u000e\u0010\u0005\u001a\n \u0004*\u0004\u0018\u00010\u00060\u0006H\n\u00a2\u0006\u0004\u0008\u0007\u0010\u0008"}, d2={"<anonymous>", "", "a", "", "kotlin.jvm.PlatformType", "b", "", "call", "(Ljava/lang/Character;Ljava/lang/Long;)Ljava/lang/String;"})
  OUTERCLASS net/println/kt07/LambdaKt main ([Ljava/lang/String;)V
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$1 null null
  // compiled from: Lambda.kt
}


// ================net/println/kt07/LambdaKt$sam$Action1$75bbf535.class =================
// class version 50.0 (50)
// access flags 0x30
final class net/println/kt07/LambdaKt$sam$Action1$75bbf535 implements rx/functions/Action1  {


  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3)

  // access flags 0x1012
  private final synthetic Lkotlin/jvm/functions/Function1; function

  // access flags 0x0
  <init>(Lkotlin/jvm/functions/Function1;)V
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    ALOAD 0
    ALOAD 1
    PUTFIELD net/println/kt07/LambdaKt$sam$Action1$75bbf535.function : Lkotlin/jvm/functions/Function1;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x1011
  // signature (TT;)V
  // declaration: void call(T)
  public final synthetic call(Ljava/lang/Object;)V
   L0
    ALOAD 0
    GETFIELD net/println/kt07/LambdaKt$sam$Action1$75bbf535.function : Lkotlin/jvm/functions/Function1;
    ALOAD 1
    INVOKEINTERFACE kotlin/jvm/functions/Function1.invoke (Ljava/lang/Object;)Ljava/lang/Object;
    DUP
    LDC "invoke(...)"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkExpressionValueIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    POP
    RETURN
   L1
    LOCALVARIABLE this Lrx/functions/Action1; L0 L1 0
    LOCALVARIABLE t Ljava/lang/Object; L0 L1 1
    MAXSTACK = 3
    MAXLOCALS = 2
  // compiled from: Lambda.kt
}


// ================net/println/kt07/LambdaKt$main$2.class =================
// class version 50.0 (50)
// access flags 0x30
// signature Lkotlin/jvm/internal/FunctionReference;Lkotlin/jvm/functions/Function1<Ljava/lang/Object;Lkotlin/Unit;>;
// declaration: net/println/kt07/LambdaKt$main$2 extends kotlin.jvm.internal.FunctionReference implements kotlin.jvm.functions.Function1<java.lang.Object, kotlin.Unit>
final class net/println/kt07/LambdaKt$main$2 extends kotlin/jvm/internal/FunctionReference  implements kotlin/jvm/functions/Function1  {


  // access flags 0x1041
  public synthetic bridge invoke(Ljava/lang/Object;)Ljava/lang/Object;
    ALOAD 0
    ALOAD 1
    INVOKEVIRTUAL net/println/kt07/LambdaKt$main$2.invoke (Ljava/lang/Object;)V
    GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x11
  public final invoke(Ljava/lang/Object;)V
    @Lorg/jetbrains/annotations/Nullable;() // invisible, parameter 0
   L0
    LINENUMBER 20 L0
   L1
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L2
   L3
    RETURN
   L4
    LOCALVARIABLE this Lnet/println/kt07/LambdaKt$main$2; L0 L4 0
    LOCALVARIABLE p1 Ljava/lang/Object; L0 L4 1
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x11
  public final getOwner()Lkotlin/reflect/KDeclarationContainer;
    LDC Lkotlin/io/ConsoleKt;.class
    LDC "production sources for module kt07_main"
    INVOKESTATIC kotlin/jvm/internal/Reflection.getOrCreateKotlinPackage (Ljava/lang/Class;Ljava/lang/String;)Lkotlin/reflect/KDeclarationContainer;
    ARETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x11
  public final getName()Ljava/lang/String;
    LDC "println"
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x11
  public final getSignature()Ljava/lang/String;
    LDC "println(Ljava/lang/Object;)V"
    ARETURN
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x0
  <init>()V
    ALOAD 0
    ICONST_1
    INVOKESPECIAL kotlin/jvm/internal/FunctionReference.<init> (I)V
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 1

  // access flags 0x19
  public final static Lnet/println/kt07/LambdaKt$main$2; INSTANCE

  // access flags 0x8
  static <clinit>()V
    NEW net/println/kt07/LambdaKt$main$2
    DUP
    INVOKESPECIAL net/println/kt07/LambdaKt$main$2.<init> ()V
    PUTSTATIC net/println/kt07/LambdaKt$main$2.INSTANCE : Lnet/println/kt07/LambdaKt$main$2;
    RETURN
    MAXSTACK = 2
    MAXLOCALS = 0

  @Lkotlin/Metadata;(mv={1, 1, 6}, bv={1, 0, 1}, k=3, d1={"\u0000\u0014\n\u0000\n\u0002\u0010\u0002\n\u0000\n\u0002\u0010\u0000\n\u0002\u0018\u0002\n\u0002\u0008\u0003\u0010\u0000\u001a\u00020\u00012\u0017\u0010\u0002\u001a\u0013\u0018\u00010\u0003\u00a2\u0006\u000c\u0008\u0004\u0012\u0008\u0008\u0005\u0012\u0004\u0008\u0008(\u0006\u00a2\u0006\u0002\u0008\u0007"}, d2={"<anonymous>", "", "p1", "", "Lkotlin/ParameterName;", "name", "message", "invoke"})
  OUTERCLASS net/println/kt07/LambdaKt main ([Ljava/lang/String;)V
  // access flags 0x18
  final static INNERCLASS net/println/kt07/LambdaKt$main$2 null null
  // compiled from: Lambda.kt
  // debug info: SMAP
Lambda.kt
Kotlin
*S Kotlin
*F
+ 1 Lambda.kt
net/println/kt07/LambdaKt$main$2
*L
1#1,28:1
*E

}


// ================META-INF/production sources for module kt07_main.kotlin_module =================


net.println.kt07LambdaKt

Android 也没有问题

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        verticalLayout{
            imageView {
                async {
                    imageBitmap = await{ loadImage(url) }
                }
            }
        }
    }
}

编译成 JavaScript

import kotlin.browser.document

fun main(args: Array<String>) {
    document.writeln("Hello World from Kotlin-js")
}
if (typeof kotlin === 'undefined') {
  throw new Error("Error loading module 'kotlin-javascript'. Its dependency 'kotlin' was not found. Please, check whether 'kotlin' is loaded prior to 'kotlin-javascript'.");
}
this['kotlin-javascript'] = function (_, Kotlin) {
  'use strict';
  function main(args) {
    document.writeln('Hello World from ' + browerInfoString());
  }
  _.main_kand9s$ = main;
  Kotlin.defineModule('kotlin-javascript', _);
  main([]);
  return _;
}(typeof this['kotlin-javascript'] === 'undefined' ? {} : this['kotlin-javascript'], kotlin);

Native 编译 与 C 兼容

#ifndef CN_KOTLINER_H
#define CN_KOTLINER_H

void printHello();

int factorial(int n);

#endif
package cn.kotliner.native

import konan.SymbolName
import kotlinx.cinterop.*

@SymbolName("kni_cn_kotliner_native_printHello")
external fun printHello(): Unit

@SymbolName("kni_cn_kotliner_native_factorial")
external fun factorial(n: Int): Int

Kotlin 给我们带来什么

简洁性

data class Customer(
    val name: String, 
    val email: String, 
    val company: String)

数据类

val positiveNumbers = list.filter { it > 0 }

Lambda表达式

单例

object ThisIsASingleton {
    val companyName: String = "JetBrains"
}

异步

async {
    val bitmap = await{ loadImage(url) }
}

安全性

override 关键字

空类型安全

var output: String
output = null   // Compilation error
override fun doTask(){
    ...
}

主构造器

class PhoneCall(val id: String){

    constructor(val id: String, val caller: String): this(id){
        ...
    }
}

通用性

都有谁在用 Kotlin

JetBrains

Kotlin 的诞生地

IntelliJ 全家桶的开发语言

Google

Android 官方开发语言

Android 官方开发语言

Android 官方开发语言

Square

Jake Wharton 的公司

大神已经贡献了不少 Kotlin 框架

沪江

绝大部分代码已经替换为 Kotlin,是国内较早采用 Kotlin 的公司

 

花瓣网

Android app 100% 使用 Kotlin 开发

快乐迭代

不要 Java,只用 Kotlin 的公司

Coursera

Android app 部分代码使用 Kotlin 开发

Uber

主要用来开发内部工具,例如Gradle 插件、注解处理器等等

你该不该用 Kotlin

用 Kotlin 开发 Android 靠谱吗?

  • Google 说,靠谱啊
  • Jake Wharton 大神早就说,性能没问题,放心大胆地用
  • 国内有不少公司尝试,还没听说不好的
  • 问题:需要与你的协作者沟通好

用 Kotlin 开发服务端靠谱吗?

  • Spring 说靠谱啊
  • 可直接使用  Java 的框架
  • 纯 Kotlin 框架例如 ktor 
  • 问题:跟你的协作者沟通好

Kotlin 会不会慢慢把 Java 取代了?

  • 短期内不会,而且我们也没必要担心这个
  • 不会写 Kotlin 的人倒是可能被 Java&Kotlin 给淘汰掉

Kotlin 学习资料

公众号 Kotlin

  • 周一发文
  • 技术干货
  • 社区动态

Kotlin 中文网

Kotlin 中文社区

Kotlin 中文博客

KotlinThree

视频教程

实例展示

Gradle 配置

group 'net.println.kotlin'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.1.2-2'

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

apply plugin: 'java'
apply plugin: 'kotlin'

sourceCompatibility = 1.5

repositories {
    mavenCentral()
}

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    testCompile group: 'junit', name: 'junit', version: '4.11'
}

Hello World

**
 * Created by benny on 2/18/17.
 */
fun main(args: Array<String>) {
    println("Hello World")
}

when 表达式

fun main(args: Array<String>) {
    val x = 5
    when(x){
        is Int -> println("Hello $x")
        in 1..100 -> println("$x is in 1..100")
        !in 1..100 -> println("$x is not in 1..100")
        args[0].toInt() -> println("x == args[0]")
    }

    val mode = when{
        args.isNotEmpty() && args[0] == "1" -> 1
        else -> 0
    }.let(::println)
}

try-catch 表达式

fun main(args: Array<String>) {
    val result = try{
        args[0].toInt() / args[1].toInt()
    }catch (e: Exception){
        0
    }
    println(result)
}

输入:100 50

扩展方法

fun main(args: Array<String>) {
    println("*" * 16)
}

operator fun String.times(int: Int): String{
    val stringBuilder = StringBuilder()
    for(i in 0 until int){
        stringBuilder.append(this)
    }
    return stringBuilder.toString()
}

数据类

data class Country(val id: Int, val name: String)

fun main(args: Array<String>) {
    val china = Country(0, "中国")
    println(china)
    println(china.component1())
    println(china.component2())
    val (id, name) = china
    println(id)
    println(name)
}

科里化

fun <P1, P2, P3, R> Function3<P1, P2, P3, R>.curried()
    = fun(p1: P1) = fun(p2: P2) = fun(p3: P3) = this(p1, p2, p3)

fun log(tag: String, target: OutputStream, message: Any?){
    target.write("[$tag] $message\n".toByteArray())
}

fun main(args: Array<String>) {
    log("benny", System.out, "HelloWorld")
    ::log.curried()("benny")(System.out)("HelloWorld Again.")
}

HTML DSL

fun main(args: Array<String>) {
    html {
        "id"("HtmlId")
        "head"{
            "id"("headId")
        }
        body {
            id="bodyId"
            `class` = "bodyClass"

            "a"{
                "href"("https://www.kotliner.cn")
                +"Kotlin 中文博客"
            }
        }
        "div"{ }
    }.render().let(::println)
}

Gradle DSL

group = "cn.kotliner.kotlin"
version = "1.0-SNAPSHOT"

buildscript {
    extra["kotlin_version"] = "1.1.2"

    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${extra["kotlin_version"]}")
    }
}

apply {
    plugin("java")
    plugin("kotlin")
}

configure<JavaPluginConvention>{
    setSourceCompatibility(1.5)
}

repositories {
    mavenCentral()
}

dependencies {
    compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${extra["kotlin_version"]}")
    testCompile("junit", "junit", "4.12")
}

协程

frame.onButtonClick {
    log("协程之前")
    我要开始协程啦(DownloadContext(LOGO_URL)) {
        log("协程开始")
        try {
            val imageData = 我要开始耗时操作了 { 
                我要开始加载图片啦(this[DownloadContext]!!.url) 
            }
            log("拿到图片")
            frame.setLogo(imageData)
        } catch(e: Exception) {      ...      }
    }
    log("协程之后")
}

Android-Support

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        fab.onClick { view ->
            Snackbar.make(view!!, 
                    "Replace with your own action", 
                    Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
            helloWorld.text = "${System.currentTimeMillis()}"

            startActivity<Main2Activity>("Key" to "From MainActivity")
        }
    }
}

Android-Support

class Main2Activity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        relativeLayout {
            textView(intent.extras["Key"]?.toString()?: "Hello") {

            }.lparams(matchParent, matchParent){
                gravity = Gravity.CENTER
            }
        }
    }
}

JavaScript-Support

fun main(args: Array<String>) {
    document.getElementById("title")?.innerHTML = "Hello World from Kotlin!!"
    val canvas = document.getElementById("myCanvas") as HTMLCanvasElement
    val cxt=canvas.getContext("2d") as CanvasRenderingContext2D
    cxt.fillStyle ="#ffffff"
    cxt.strokeStyle = "#FF0000"
    cxt.moveTo(canvas.width / 2.0, canvas.height / 2.0)
    canvas.onclick = { event ->
        if(event is MouseEvent){
            cxt.clearRect(0.0, 0.0, canvas.width.toDouble(), canvas.height.toDouble())
            cxt.lineTo(event.offsetX, event.offsetY)
            cxt.stroke()
        }
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello World Kotlin</title>
</head>
<body>
<h1 id="title">Title</h1>
<canvas id="myCanvas" width="1000px" height="500px"></canvas>
</body>
<script type="text/javascript" src="out/production/kotlin-javascript/lib/kotlin.js"></script>
<script type="text/javascript" src="js/browserinfo.js"></script>
<script type="text/javascript" src="out/production/kotlin-javascript/kotlin-javascript.js"></script>
</html>

JavaScript-Support

Native-Support

#include "cn_kotliner.h"
#include <stdio.h>

void printHello(){
    printf("[C] HelloWorld\n");
}

int factorial(int n){
    printf("[C] calc factorial: %d\n", n);
    if(n == 0) return 1;
    return n * factorial( n - 1 );
}
import cn.kotliner.native.*

fun main(args: Array<String>){
    printHello()
    (1 .. 5).map(::factorial).forEach(::println)
}

Native-Support

Q&A

Made with Slides.com