Share
Embed
菜鳥的Kotlin on Android之路
2015/11/18 @ GDG Taipei
2015/12/05 @ Jcconf 2015
https://youtu.be/22EPAdvEbfM
Nevin
December 05, 2015
Transcript
45 slides
-
Kotlin Statically typed, modern language for industry Not swift of
Android @ChenNevin -
Agenda • Overview • Kotlin Basics • Goodies • Work
with Android • Opinionated steps to adopt • Resources -
Kotlin • Build and used by JetBrain • Since 2010,
• 1.0 -Beta 2 • Tooling support • Very low learning curve -
Statically typed programming language • for Android , JVM ,
Browser • Concise , Safe , Interoperable • work with Java echo system ( libraries, JRebel , RoboVM…) -
Null safety var a: String = "abc" a = null
//compilation error var b: String? = null // OK! b = bob?.department?.name // safe call using ?. val l = b!!.length() // YOYO (NPE-lovers) -
Elvis operator val l: Int = if (b != null)
b.length else -1 val l = b?.length ?: -1 -
When when (x) { 0, 1 -> print("x == 0
or x == 1”) 2 -> print("x == 2") true -> print("true") is String -> x.startsWith("prefix") is File -> x.getFreeSpace() else -> { // Note the block print("x is funny") } } -
Smart cast / Auto cast // Once type is checked,
no need to cast again when (x) { is String -> x.length() is File -> x.getFreeSpace() else -> { // Note the block print("x is neither String nor File") } } // safe cast, x must be nullable val x: String? = y as? String -
Equity val a: Int = 10000 print(a == a) //
Prints 'true' print(a === a) // Prints ‘true' val boxedA: Int? = a val anotherBoxedA: Int? = a print(boxedA == anotherBoxedA) // 'true' print(boxedA === anotherBoxedA)// 'false' -
Equity • Smaller types are NOT implicitly converted to bigger
types val a: Int? = 1 // A boxed Int val b: Long? = a print(a == b) // Won’t compile -
Exception • Exception is an expression val a: Int? =
try { Int.parseInt("300") } catch (e: NumberFormatException) { null } • There’s no checked Exception [1] [2] -
Class • Final by default. With Android in mind •
Main constructor must be called • Parent’s constructor must be called class MyView : View { constructor(ctx: Context) : super(ctx) { } constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs) { } } -
Data class // Declaration data class Person(val name: String,var weight:
Int) val nevin = Person("Nevin",82) nevin.name = "Nevin Chen” // compile error nevin.weight = 7 // ok -
Data class val p2 = Person("Nevin", 82) val p3 =
Person("Mark", 75) println("nevin == p2: ${nevin == p2}”) // true println("nevin == p3: ${nevin == p3}”) // false println(user.copy("Max", 0.33)) -
First class citizen package boo.bar class A { fun foo(){
} } fun foo(){} -
Function fun cal(x: Int = 1, y: Int = 2){
print("x+y=${x + y}”) // string template fun main(args: Array<String>) { val a = A() cal(1) //default value cal(x = 3) a.cal(x = 4, y = 5) // named param } -
Function fun sum(x: Int, y: Int): Int { return x
+ y } fun sum(x: Int, y: Int): Int = x + y fun sum(x: Int, y: Int) = x + y -
Lambda expression • Also referred as function literal • Surrounded
by curly braces, • parameters (if any) are declared before -> • The body goes after -> -
Lambda val sum = { : Int, : Int ->
} x y x + y -
Lambda val sum : (Int,Int) -> Int = { ,
-> } x y x + y -
Function expression // function expression val sum = fun(x: Int,
y: Int): Int { return x + y } // anonymous function only val sum = fun(x: Int, y: Int): Int = x + y -
Higher-order function // function that take functions as parameter, //
or return a function fun calculate(x: Int, y: Int, formula: (Int, Int) -> Int) { println("the result is ${formula(x, y)}") } // usage fun main(args: Array<String>) { calculate(1,5,sum) calculate(1,5, { x, y -> x + y }) calculate(1,5){ x, y -> x + y } calculate(1,5,fun(x: Int, y: Int): Int = x + y ) } -
Extension Function // Extension Function fun Int.sum(other: Int): Int =
this + other // Extension Function Expressions val sum = fun Int.(other: Int): Int = this + other // usage 1.sum(2) -
Sample // scope : within the same package fun Int.beforeKitkat():
Boolean{ return this < Build.VERSION_CODES.KITKAT } if (Build.VERSION.SDK_INT.beforeKitkat()){ // do something… } -
Sample fun String.bd() = BigDecimal(this) fun main(args: Array<String>) { //0.06
println("0.05".bd().add("0.01".bd()) ) //0.060000000000000005 println(0.05+0.01) } -
Function Expression val validator: (String) -> Boolean = { it.length
> 2 } fun EditText.validateWith(check: (String) -> Boolean){ val content = this.text.toString() if (check(content)) { context.toast("Welcome $content!") } else { context.toast("Name not valid") } } -
Design Pattern • Singleton ( Object) • Delegation ( Class
/ Property Delegation ) • Decorator ( Extension Function) -
Useful crew / tool • bytecode viewer ( cmd+shift +A
-> show kotlin Bytecode) • Anko • Android extension -
Anko • Why Anko ? • type safe builder (
avoid manual casting) for view hierarchy and more • null-safe (findViewById(….) return null) • avoid XML parsing (save CPU and battery) -
Anko val layout = LinearLayout(context) layout.orientation = LinearLayout.VERTICAL val name
= EditText(act) val button = Button(act) button.text = "Say Hello" button.setOnClickListener { Toast.makeText(act, .....).show() } layout.addView(name) layout.addView(button) -
Anko verticalLayout { val name = editText() button("Say Hello") {
onClick { toast(“HI!,${name.text}!") } } } -
Anko • Anko DSL preview plugin • Design Support Library
compile ‘org.jetbrains.anko:anko-design:0.7.2’ • Work great if you create view programatically • Other good stuff -
Anko longToast("Halo")) info(“info”) warn(“warn”) debug(“debug”) async { var result =
readDataFromServer(); uiThread { warn(result + "") halo.text = result } } -
Android Extension // import import kotlinx.android.synthetic.layout.* // code txt.text= "WELCOME
!!”// use widget id directly -
Take Away • Less code , Less bug • Easy
to read and code • Lambda • Extension function -
Steps to convert • Start small (ex. convert POJO into
data class) • When you got NPE , Cast Exception • Check all !!s , make them ? or non-null • Check the difference between Java and Kotlin -
Static method • There’s no static in Kotlin. Use companion
object // Declaration class SomeClass{ companion object { fun method(){ } } } // Usage SomeClass.Companion.method() -
Immutable non-nullable val url: String by lazy { // compute
the string if (isProduction){ return@lazy "http://prod.url.com" }else{ return@lazy "http://stg.url.com" } } -
Other difference • Invariant array • No raw types •
No private fields • Smaller type is not a subtype of bigger types • Calling Java code from Kotlin • Calling Kotlin from Java -
Other tips • No bulk support, try kobalt • std-lib
: let() , apply() , with() ,run(), use() • Not a completely new language, very handy • A great place to learn functional programming • Droidcon talks may not up-to-date. Some issues are fixed. -
Other tips • How to return from lambda • Don’t
use inheritance with data class • Pass in function instead of object • Almost everything in Kotlin is an expression ( can return value) • Just “convert Java code to Kotlin” and “Config Kotlin in Project” -
Resources • Official materials , try , and Slack(#android) •
Koans web and github • Jake Wharton : Using Project Kotlin for Android and Advancing Development with the Kotlin • twitter #kotlin @cbeust @madisp [JRebel] • Links : Trending, antonio leva , Android