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

菜鳥的Kotlin on Android之路

Nevin
December 05, 2015

菜鳥的Kotlin on Android之路

2015/11/18 @ GDG Taipei
2015/12/05 @ Jcconf 2015
https://youtu.be/22EPAdvEbfM

Nevin

December 05, 2015
Tweet

More Decks by Nevin

Other Decks in Programming

Transcript

  1. Agenda • Overview • Kotlin Basics • Goodies • Work

    with Android • Opinionated steps to adopt • Resources
  2. Kotlin • Build and used by JetBrain • Since 2010,

    • 1.0 -Beta 2 • Tooling support • Very low learning curve
  3. Statically typed programming language • for Android , JVM ,

    Browser • Concise , Safe , Interoperable • work with Java echo system ( libraries, JRebel , RoboVM…)
  4. 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)
  5. Elvis operator val l: Int = if (b != null)

    b.length else -1
 
 val l = b?.length ?: -1
  6. 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")
 }
 }
  7. 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
  8. 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'
  9. 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
  10. Exception • Exception is an expression val a: Int? =

    try { Int.parseInt("300") } catch (e: NumberFormatException) { null }
 • There’s no checked Exception [1] [2]
  11. 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) {
 }
 }
  12. 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
  13. 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))
  14. 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
 }
 

  15. 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
  16. Lambda expression • Also referred as function literal • Surrounded

    by curly braces, • parameters (if any) are declared before -> • The body goes after ->
  17. 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
  18. 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 )
 }
  19. 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)
  20. Sample // scope : within the same package fun Int.beforeKitkat():

    Boolean{
 return this < Build.VERSION_CODES.KITKAT
 } if (Build.VERSION.SDK_INT.beforeKitkat()){
 // do something…
 }
  21. 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)
 }
  22. 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")
 }
 }

  23. Design Pattern • Singleton ( Object) • Delegation ( Class

    / Property Delegation ) • Decorator ( Extension Function)
  24. Useful crew / tool • bytecode viewer ( cmd+shift +A

    -> show kotlin Bytecode) • Anko • Android extension
  25. 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)
  26. 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)
  27. Anko verticalLayout {
 val name = editText()
 button("Say Hello") {


    onClick { toast(“HI!,${name.text}!") }
 }
 }
  28. 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
  29. Anko longToast("Halo"))
 info(“info”) warn(“warn”) debug(“debug”) async {
 var result =

    readDataFromServer();
 uiThread {
 warn(result + "")
 halo.text = result
 }
 }
  30. Take Away • Less code , Less bug • Easy

    to read and code • Lambda • Extension function
  31. 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
  32. Static method • There’s no static in Kotlin. Use companion

    object // Declaration class SomeClass{
 companion object {
 fun method(){
 }
 }
 } // Usage SomeClass.Companion.method()
  33. 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"
 }
 }
  34. 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
  35. 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.
  36. 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”
  37. 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