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

Succumb to the Kotlin side

Succumb to the Kotlin side

Introduction talk to Kotlin for Android developers.

Alberto Ballano

March 01, 2016
Tweet

More Decks by Alberto Ballano

Other Decks in Programming

Transcript

  1. Constructors data class Person(val firstName: String = "Alberto"){} • equals()/hashCode()

    • toString() of the form "Person(firstName=Alberto)" • componentN() functions • copy()
  2. Constructors data class Person(val firstName: String = "Alberto"){} // val

    alberto = Person() val joe = Person("Joe") Ok, but...
  3. Constructors data class Person(val firstName: String = "Alberto"){} // val

    alberto = Person() val joe = Person("Joe") Where´s the “new”?
  4. Constructors data class Person(val firstName: String = "Alberto"){} // val

    alberto = Person() val joe = Person("Joe") Where´s the “new”? and the semicolon!?
  5. Functions fun read(items: Array<Int>, offset: Int = 0, length: Int

    = items.size()) { // ... } read(ArrayOf(1, 2, 3))
  6. Functions fun read(items: Array<Int>, offset: Int = 0, length: Int

    = items.size()) { // ... } read(ArrayOf(1, 2, 3), length = 1)
  7. Control flow (I) var max: Int if (a > b)

    //do some stuff max = a else //do some stuff max = b
  8. Control flow (I) var max: Int if (a > b)

    //do some stuff max = a else //do some stuff max = b (but… if is now an expression)
  9. Control flow (I) var max = if (a > b)

    //do some stuff a else //do some stuff b (if branches can be blocks, and the last expression is the value of a block)
  10. Control flow (I) var max = if (a > b)

    a else b (and for simpler ifs...)
  11. Control flow (II) when (x) { 0, 1 -> print("x

    is 0 or 1") 2 -> print("x is 2") }
  12. Control flow (II) when (x) { in 1..10 -> print("x

    is in the range") in validNumbers -> print("x is valid") !in 10..20 -> print("x is outside the range") else -> print("none of the above") } (validNumbers is a collection)
  13. Control flow (II) val hasPrefix = when(x) { is String

    -> x.startsWith("prefix") else -> false } (since here when is an expression we’re forced to put the else)
  14. Control flow (II) val hasPrefix = when(x) { is String

    -> x.startsWith("prefix") else -> false } (since here when is an expression we’re forced to put the else)
  15. Control flow (extra) if (obj is String) { // At

    this point obj is magically a String! print(obj.length) }
  16. Null safety var a: String = "abc" a = null

    a.capitalize() Kotlin Quiz a) NullPointerException
  17. Null safety var a: String = "abc" a = null

    a.capitalize() Kotlin Quiz a) NullPointerException b) Compilation error
  18. Null safety var a: String = "abc" a = null

    a.capitalize() Kotlin Quiz a) NullPointerException b) Compilation error c) Nothing, the method won´t be executed
  19. Null safety var a: String = "abc" a = null

    a.capitalize() Kotlin Quiz a) NullPointerException b) Compilation error c) Nothing, the method won´t be executed d) Assertion error
  20. Null safety var a: String = "abc" a = null

    a.capitalize() Kotlin Quiz a) NullPointerException b) Compilation error c) Nothing, the method won´t be executed d) Assertion error e) I really think it´s a NullPointerException
  21. Null safety var a: String = "abc" a = null

    // compilation error a.capitalize()
  22. Null safety var a: String? = "abc" a = null

    a.capitalize() // compilation error
  23. Null safety var a: String? = "abc" a = null

    if (a != null) { a.capitalize() }
  24. Null safety var a: String? = "abc" a = null

    if (a != null) { // boring a.capitalize() }
  25. Null safety var a: String? = "abc" a = null

    if (a != null) { // boring a.capitalize() } // 3 lines
  26. Null safety var a: String? = "abc" a = null

    if (a != null) { // boring a.capitalize()// 17 characters for a null-check } // 3 lines
  27. Null safety var a: String? = "abc" a = null

    a ?.capitalize() // 1 char
  28. Null safety var a: String? = "abc" a = null

    a ?.capitalize() // 1 char, 16 less than before :)
  29. Null safety var a: String? = "abc" var b =

    if (a != null) { a.capitalize() } else { "" }
  30. Object object StuffManager { fun registerStuff(stuff: Stuff) { // ...

    } val allStuffs: Collection<Stuff> get() = // ... } // This is an Object declaration
  31. Object object StuffManager { fun registerStuff(stuff: Stuff) { // ...

    } val allStuffs: Collection<Stuff> get() = // ... } // This is an Object declaration Hello singleton!
  32. Extension Functions // Java code public static void hideImage(ImageView image)

    { image.setVisibility(View.GONE); image.setImageResource(0); } UiUtils.hideImage(new ImageView(context));
  33. Extension Functions // Kotlin magic fun ImageView.hide() { visibility =

    View.GONE setImageResource(0) } // import com.xing.core.extensions.hide ImageView(context).hide()
  34. Higher-Order Functions fun <T> logException(func: () -> T): T? {

    try { return func() } catch (ignored: Throwable) { Log.e("ERROR", "...") return null } }
  35. Higher-Order Functions fun <T> logException(func: () -> T) = try

    { return func() } catch (ignored: Throwable) { Log.e("ERROR", "...") return null }
  36. Higher-Order Functions inline fun <T> logException(func: () -> T) =

    try { return func() } catch (ignored: Throwable) { Log.e("ERROR", "...") return null }
  37. Higher-Order Functions inline fun <T> logException(func: () -> T) =

    try { return func() } catch (ignored: Throwable) { Log.e("ERROR", "...") return null } // ... logException({ myDangerousMethod() })
  38. Higher-Order Functions inline fun <T> logException(func: () -> T) =

    try { return func() } catch (ignored: Throwable) { Log.e("ERROR", "...") return null } // ... logException { myDangerousMethod() }
  39. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) val

    edit = prefs.edit() edit.putBoolean("enabled", true) edit.commit()
  40. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabled", true) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() }
  41. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabledCount", 1) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() }
  42. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabledCount", 1) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() } fun edit(key: String, value: Int) { prefs.edit().putInt(key, value).commit() }
  43. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabledCount", 1F) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() } fun edit(key: String, value: Int) { prefs.edit().putInt(key, value).commit() }
  44. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabledCount", 1F) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() } fun edit(key: String, value: Int) { prefs.edit().putInt(key, value).commit() } fun edit(key: String, value: Float) { prefs.edit().putFloat(key, value).commit() }
  45. Extensions + High-Order = Awesomeness val prefs = context.getSharedPreferences(...) //

    in some method... edit("enabledCount", 1L) fun edit(key: String, value: Boolean) { prefs.edit().putBoolean(key, value).commit() } fun edit(key: String, value: Int) { prefs.edit().putInt(key, value).commit() } fun edit(key: String, value: Float) { prefs.edit().putFloat(key, value).commit() }
  46. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: ()

    -> Unit) { val editor = edit() func() editor.commit() }
  47. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: ()

    -> Unit) { val editor = edit() func() editor.commit() } prefs.inEdit { prefs.putBoolean(...) }
  48. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: ()

    -> Unit) { val editor = edit() func() editor.commit() } prefs.inEdit { prefs.putBoolean(...) }
  49. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: (SharedPreferences.Editor)

    -> Unit) { val editor = edit() func() editor.commit() } prefs.inEdit { prefs.putBoolean(...) }
  50. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: (SharedPreferences.Editor)

    -> Unit) { val editor = edit() func(editor) editor.commit() } prefs.inEdit { prefs.putBoolean(...) }
  51. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: (SharedPreferences.Editor)

    -> Unit) { val editor = edit() func(editor) editor.commit() } prefs.inEdit { editor -> editor.putBoolean(...) }
  52. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: (SharedPreferences.Editor)

    -> Unit) { val editor = edit() func(editor) editor.commit() } prefs.inEdit { it.putBoolean(...) }
  53. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: SharedPreferences.Editor.()

    -> Unit) { val editor = edit() func(editor) editor.commit() } prefs.inEdit { it.putBoolean(...) }
  54. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: SharedPreferences.Editor.()

    -> Unit) { val editor = edit() editor.func() editor.commit() } prefs.inEdit { it.putBoolean(...) }
  55. Extensions + High-Order = Awesomeness inline fun SharedPreferences.inEdit( func: SharedPreferences.Editor.()

    -> Unit) { val editor = edit() editor.func() editor.commit() } prefs.inEdit { putBoolean(...) }
  56. Android extensions import kotlinx.android.synthetic.main.activity_main.* class MyActivity : Activity() { override

    fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Instead of findView(R.id.textView) as TextView textView.text = "Hello, world!" } }
  57. Examples (1) Bundle args = getArguments() if (args != null)

    { String data = args.getString(DATA_ARG) if (data != null) { data.getBytes() } }
  58. Examples (1) Bundle args = getArguments() if (args != null)

    { String data = args.getString(DATA_ARG) if (data != null) { data.getBytes() } }
  59. Examples (2) fun View.hideKeyboard() { imm = getContext().getSystemService( Context.INPUT_METHOD_SERVICE) as

    InputMethodManager imm.hideSoftInputFromWindow(getWindowToken(), 0) }
  60. Examples (2) fun View.hideKeyboard() { imm = getContext().getSystemService( Context.INPUT_METHOD_SERVICE) as

    InputMethodManager imm.hideSoftInputFromWindow(getWindowToken(), 0) } yourEditText.hideKeyboard()
  61. What can be optimized • Every Utils class • Duplicated

    boilerplate code ◦ Model classes ◦ Actions we do in single objects (Picasso) • Whenever you have to write the same word multiple times (almost)
  62. Is it worth? Well, that's up to one person… (and

    your coworkers) (and your tech lead)
  63. Is it worth? Well, that's up to one person… (and

    your coworkers) (and your tech lead) (and you might want to tell your PO as well…)
  64. Is it worth? Well, that's up to one person… (and

    your coworkers) (and your tech lead) (and you might want to tell your PO as well…) (yeah, better create a meeting for that)
  65. Is it worth? Well, that's up to one person… (and

    your coworkers) (and your tech lead) (and you might want to tell your PO as well…) (yeah, better create a meeting for that) Silver Bullet principle
  66. Q&A