Kotlin + Android

Kotlin + Android

Brief overview of Kotlin syntax and features for GDG Lviv Android Spring Barcamp 2016

56d515afd6a1001e8264df0d96c7a80e?s=128

Dmytro Danylyk

April 21, 2016
Tweet

Transcript

  1. 2.
  2. 6.

    How to add Kotlin to your project? 2. Declare dependencies

    buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin-android' dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" }
  3. 7.

    How to add Kotlin to your project? 2. Declare dependencies

    buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin-android' dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" }
  4. 9.

    What does it look like? val a: Int = 1

    val b = 1 Int type is inferred
  5. 10.

    What does it look like? val a: Int = 1

    val b = 1 var c: Int Mutable variable
  6. 11.

    What does it look like? val a: Int = 1

    val b = 1 var c: Int c = 2
  7. 12.

    What does it look like? val a: Int = 1

    val b = 1 var c: Int c = 2 val date = Date() print(date.time) Instances of class
  8. 13.

    What does it look like? class Main { fun printSum(a:

    Int, b: Int) { print(a + b) } fun returnSum(a: Int, b: Int): Int { return a + b } } Class name
  9. 14.

    What does it look like? class Main { fun printSum(a:

    Int, b: Int) { print(a + b) } fun returnSum(a: Int, b: Int): Int { return a + b } }
  10. 15.

    What does it look like? class Main { fun printSum(a:

    Int, b: Int) { print(a + b) } fun returnSum(a: Int, b: Int): Int { return a + b } } Function name
  11. 16.

    What does it look like? class Main { fun printSum(a:

    Int, b: Int) { print(a + b) } fun returnSum(a: Int, b: Int): Int { return a + b } } Function arguments
  12. 17.

    What does it look like? class Main { fun printSum(a:

    Int, b: Int) { print(a + b) } fun returnSum(a: Int, b: Int): Int { return a + b } } Return type
  13. 18.

    Kotlin Features String templates Properties Lambdas Data class Smart cast

    Null safety Default values for function parameters Lazy property Extension Functions Single-expression functions When expression let, apply, use, with Collections Kotlin Android Extensions Plugin Anko
  14. 19.

    String templates val query = "Kotlin" val language = "en"

    val url = "https://www.google.com.ua/#q=$query&language=$language"
  15. 20.

    String templates val query = "Kotlin" val language = "en"

    val url = "https://www.google.com.ua/#q=$query&language=$language"
  16. 21.

    String templates val query = "Kotlin" val language = "en"

    val url = "https://www.google.com.ua/#q=$query&language=$language" > https://www.google.com.ua/#q=Kotlin&language=en
  17. 23.

    Properties class User { var name: String? = null var

    age: Int? = null } val user = User() user.name = "John" user.age = 24 print("User name:${user.name}")
  18. 24.

    Properties class User { var name: String? = null var

    age: Int? = null set(value) { if (value >= 0) field = value } }
  19. 35.

    Data class • getters, setters • equals()/hashCode() • toString() of

    the form "User(name=John, age=42)" • copy() function Nothing, just hold data What it does? What it provides?
  20. 37.

    Data class data class User(val name: String, val age: Int)

    val user = User("Dmytro", 24) print(user) > User(name=Dmytro, age=24)
  21. 38.

    Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } }
  22. 39.

    Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } } x is automatically cast to String
  23. 40.

    Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } } x is automatically cast to Int
  24. 41.

    Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } }
  25. 43.

    Null safety var name: String = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") }
  26. 44.

    Null safety var name: String = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") } Compilation error, non null variable
  27. 45.

    Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") }
  28. 46.

    Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") } Compilation error, argument may be null
  29. 47.

    Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState?.getString("name") }
  30. 48.

    Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState?.getString("name") }
  31. 49.

    Default values for function parameters Function parameters can have default

    values, which are used when a corresponding argument is omitted. This allows for a reduced number of overloads compared to other languages.
  32. 50.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String?, selectionArgs : Array<String>?, orderBy: String?): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), null, null, "NAME")
  33. 51.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String? = null, selectionArgs : Array<String>? = null, orderBy: String? = null): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), null, null, "NAME") Default value
  34. 52.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String? = null, selectionArgs : Array<String>? = null, orderBy: String? = null): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), null, null, "NAME")
  35. 53.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String? = null, selectionArgs : Array<String>? = null, orderBy: String? = null): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), null, null, orderBy = "NAME") Named argument
  36. 54.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String? = null, selectionArgs : Array<String>? = null, orderBy: String? = null): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), null, null, orderBy = "NAME") Not need
  37. 55.

    Default values for function parameters fun query(table: String, columns: Array<String>,

    selection: String? = null, selectionArgs : Array<String>? = null, orderBy: String? = null): Cursor { ... } // function call query("USERS", arrayOf("ID", "NAME"), orderBy = "NAME")
  38. 57.

    Lazy property val preference = getSharedPreferences("pref") override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val username = preference.getString("username") }
  39. 58.

    Lazy property val preference = getSharedPreferences("pref") override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val username = preference.getString("username") } Crash, require context
  40. 59.

    Lazy property val preference by lazy { getSharedPreferences("pref") } override

    fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val username = preference.getString("username") } Won’t be executed until the property is first used
  41. 60.

    Lazy property val preference by lazy { getSharedPreferences("pref") } override

    fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val username = preference.getString("username") }
  42. 61.

    Extension Functions Extensions do not actually modify classes they extend.

    By defining an extension, you do not insert new members into a class, but merely make new functions callable with the dot-notation on instances of this class. Provides the ability to extend a class with new functionality without having to inherit from the class. What it does? How?
  43. 66.

    Single-expression functions When a function returns a single expression, the

    curly braces can be omitted and the body is specified after a = symbol.
  44. 74.

    When expression when (argument) { match1 -> fun1() match2 ->

    fun2() else -> fun3() } Can be anything
  45. 75.

    When expression when (argument) { match1 -> fun1() match2 ->

    fun2() else -> fun3() } Can be anything
  46. 76.

    When expression var result: Int = when (argument) { match1

    -> fun1() match2 -> fun2() else -> fun3() } Can return result
  47. 77.

    When expression var result: Int = when (argument) { match1

    -> fun1() match2 -> fun2() else -> fun3() }
  48. 78.

    When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) { when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g)) } return null }
  49. 79.

    When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) { when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g)) } return null } Can be placed after a = symbol
  50. 80.

    When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) = when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g)) else -> null }
  51. 81.

    When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) = when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g) else -> null }
  52. 82.

    When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED }
  53. 83.

    When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED } Type checks possible
  54. 84.

    When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED }
  55. 85.

    When expression override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) { val

    displayable: Displayable = dataList[index] when (displayable) { is Title -> initTitle(viewHolder, displayable) is Description -> initDescription(viewHolder, displayable) } }
  56. 86.

    When expression override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) { val

    displayable: Displayable = dataList[index] when (displayable) { is Title -> initTitle(viewHolder, displayable) is Description -> initDescription(viewHolder, displayable) } } Smart cast
  57. 87.

    When expression override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) { val

    displayable: Displayable = dataList[index] when (displayable) { is Title -> initTitle(viewHolder, displayable) is Description -> initDescription(viewHolder, displayable) } }
  58. 88.

    let, apply, use, with Higher-order functions - function that takes

    functions as parameters, or returns a function.
  59. 89.

    let (scope function) /** * Calls the specified function [block]

    with `this` value as * its argument and returns its result. */ public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
  60. 95.

    use (try with resources function) /** * Executes the given

    [block] function on this resource and then * closes it down correctly whether an exception is thrown or not. */ public inline fun <T : Closeable, R> T.use(block: (T) -> R): R { var closed = false try { return block(this) } catch (e: Exception) { // ommitted } finally { if (!closed) { close() } } }
  61. 96.

    use fun countUsers(): Long { val database = openDatabase() val

    result = database.count("users") database.close() return result }
  62. 100.

    with /** * Calls the specified function [block] with the

    given [receiver] * as its receiver and returns its result. */ public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
  63. 106.

    apply /** * Calls the specified function [block] with `this`

    value as its receiver * and returns `this` value. */ public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
  64. 107.

    apply fun makeDir(path: String): File { val result: File =

    File(path) result.mkdirs() return result }
  65. 109.

    Collections val numbers: MutableList<Int> = mutableListOf(1, 2, 3) numbers.add(1) val

    numbers2: List<Int> = listOf(1, 2, 3) numbers2.add(1) No such method
  66. 110.

    Collections mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7,

    8, 9) .filterNotNull() .filter { it % 2 == 0 } .sortedDescending() > [1, null, 2, null, 3, 4, 5, 6, 7, 8, 9]
  67. 111.

    Collections mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7,

    8, 9) .filterNotNull() .filter { it % 2 == 0 } .sortedDescending() > [1, 2, 3, 4, 5, 6, 7, 8, 9]
  68. 112.

    Collections mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7,

    8, 9) .filterNotNull() .filter { it % 2 == 0 } .sortedDescending() > [2, 4, 6, 8]
  69. 113.

    Collections mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7,

    8, 9) .filterNotNull() .filter { it % 2 == 0 } .sortedDescending() > [8, 6, 4, 2]
  70. 114.

    Collections getOrElse() find() filter() filterNot() filterNotNull() flatMap() take() takeLast() sortBy()

    sortByDescending() groupBy() map() mapNotNull() all() any() maxBy() minBy() minWith() sumBy() zip() ...
  71. 115.

    Kotlin Android Extensions Plugin Adds a hidden caching function and

    a field inside each Kotlin Activity. Provides reference to all layout views (which have id’s) with single line of code. What it does? How?
  72. 117.

    Kotlin Android Extensions Plugin // R.layout.activity_main import kotlinx.android.synthetic.main.activity_main.* public class

    MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) txtTitle.setText("Hello, Kotlin!") btnHello.setOnClickListener {...} } }
  73. 118.

    Kotlin Android Extensions Plugin // R.layout.activity_main import kotlinx.android.synthetic.main.activity_main.* public class

    MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) txtTitle.setText("Hello, Kotlin!") btnHello.setOnClickListener {...} } }
  74. 119.

    Kotlin Android Extensions Plugin // R.layout.activity_main import kotlinx.android.synthetic.main.activity_main.* public class

    MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) txtTitle.setText("Hello, Kotlin!") btnHello.setOnClickListener {...} } } Instead of findView(R.id.txtTitle)
  75. 120.

    Kotlin Android Extensions Plugin // R.layout.activity_main import kotlinx.android.synthetic.main.activity_main.* public class

    MyActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) txtTitle.setText("Hello, Kotlin!") btnHello.setOnClickListener {...} } }
  76. 121.

    Anko Kotlin library from JetBrains which provide API to make

    Android application development faster and easier. What it does?
  77. 124.

    Anko alert("Santa", "You were a good boy?") { positiveButton("Yes") {

    toast("You are now in GOOD list") } negativeButton("No") { toast("You are now in BAD list") } }.show() val countries = listOf("Ukraine", "USA", "UK",) selector("Where are you from?", countries) { i -> toast("So you're living in ${countries[i]}, right?") }
  78. 125.

    Anko async() { // long background task uiThread { //

    won't be executed if isFinishing() is true toolbar.title = "Done" } }
  79. 126.

    Anko database.use { createTable("Customer", ifNotExists = true, "_id" to INTEGER

    + PRIMARY_KEY + UNIQUE, "name" to TEXT, "photo" to BLOB) }