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

Kotlin + Android

Kotlin + Android

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

Dmytro Danylyk

April 21, 2016
Tweet

More Decks by Dmytro Danylyk

Other Decks in Programming

Transcript

  1. 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" }
  2. 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. What does it look like? val a: Int = 1

    val b = 1 Int type is inferred
  4. What does it look like? val a: Int = 1

    val b = 1 var c: Int Mutable variable
  5. What does it look like? val a: Int = 1

    val b = 1 var c: Int c = 2
  6. 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
  7. 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
  8. 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 } }
  9. 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
  10. 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
  11. 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
  12. 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
  13. String templates val query = "Kotlin" val language = "en"

    val url = "https://www.google.com.ua/#q=$query&language=$language"
  14. String templates val query = "Kotlin" val language = "en"

    val url = "https://www.google.com.ua/#q=$query&language=$language"
  15. 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
  16. 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}")
  17. Properties class User { var name: String? = null var

    age: Int? = null set(value) { if (value >= 0) field = value } }
  18. 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?
  19. Data class data class User(val name: String, val age: Int)

    val user = User("Dmytro", 24) print(user) > User(name=Dmytro, age=24)
  20. Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } }
  21. 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
  22. 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
  23. Smart cast fun demo(x: Any) { if (x is String)

    { print(x.length) } else if (x is Int) { print(x * x) } }
  24. Null safety var name: String = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") }
  25. Null safety var name: String = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") } Compilation error, non null variable
  26. Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") }
  27. Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState.getString("name") } Compilation error, argument may be null
  28. Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState?.getString("name") }
  29. Null safety var name: String? = null override fun onCreate(savedInstanceState:

    Bundle?) { super.onCreate(savedInstanceState) name = savedInstanceState?.getString("name") }
  30. 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.
  31. 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")
  32. 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
  33. 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")
  34. 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
  35. 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
  36. 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")
  37. Lazy property val preference = getSharedPreferences("pref") override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val username = preference.getString("username") }
  38. Lazy property val preference = getSharedPreferences("pref") override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val username = preference.getString("username") } Crash, require context
  39. 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
  40. Lazy property val preference by lazy { getSharedPreferences("pref") } override

    fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val username = preference.getString("username") }
  41. 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?
  42. Single-expression functions When a function returns a single expression, the

    curly braces can be omitted and the body is specified after a = symbol.
  43. When expression when (argument) { match1 -> fun1() match2 ->

    fun2() else -> fun3() } Can be anything
  44. When expression when (argument) { match1 -> fun1() match2 ->

    fun2() else -> fun3() } Can be anything
  45. When expression var result: Int = when (argument) { match1

    -> fun1() match2 -> fun2() else -> fun3() } Can return result
  46. When expression var result: Int = when (argument) { match1

    -> fun1() match2 -> fun2() else -> fun3() }
  47. When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) { when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g)) } return null }
  48. 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
  49. When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) = when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g)) else -> null }
  50. When expression override fun onCreateViewHolder(g: ViewGroup, type: Int) = when

    (type) { TYPE_TITLE -> TitleViewHolder(g) TYPE_DESCRIPTION -> DescriptionViewHolder(g) else -> null }
  51. When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED }
  52. When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED } Type checks possible
  53. When expression override fun getItemViewType(index: Int) = when (dataList[index]) {

    is Title -> TYPE_TITLE is Description -> TYPE_DESCRIPTION else -> TYPE_UNDEFINED }
  54. 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) } }
  55. 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
  56. 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) } }
  57. let, apply, use, with Higher-order functions - function that takes

    functions as parameters, or returns a function.
  58. 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)
  59. 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() } } }
  60. use fun countUsers(): Long { val database = openDatabase() val

    result = database.count("users") database.close() return result }
  61. 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()
  62. 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 }
  63. apply fun makeDir(path: String): File { val result: File =

    File(path) result.mkdirs() return result }
  64. 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
  65. 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]
  66. 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]
  67. Collections mutableListOf(1, null, 2, null, 3, 4, 5, 6, 7,

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

    8, 9) .filterNotNull() .filter { it % 2 == 0 } .sortedDescending() > [8, 6, 4, 2]
  69. Collections getOrElse() find() filter() filterNot() filterNotNull() flatMap() take() takeLast() sortBy()

    sortByDescending() groupBy() map() mapNotNull() all() any() maxBy() minBy() minWith() sumBy() zip() ...
  70. 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?
  71. 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 {...} } }
  72. 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. 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)
  74. 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 {...} } }
  75. Anko Kotlin library from JetBrains which provide API to make

    Android application development faster and easier. What it does?
  76. 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?") }
  77. Anko async() { // long background task uiThread { //

    won't be executed if isFinishing() is true toolbar.title = "Done" } }
  78. Anko database.use { createTable("Customer", ifNotExists = true, "_id" to INTEGER

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