Life is great and everything will be OK, Kotlin is here (Google IO 2017)

Life is great and everything will be OK, Kotlin is here (Google IO 2017)

Using Kotlin for Android development has grown in popularity over the past few years and is now officially supported by Google. If you are not already using Kotlin you might be wondering why and how to adopt it. In the first part of this talk, Jake will cover advancing the usage and design patterns of the language for Android development to solve larger problems. In the second part, Christina will share her experience using Kotlin in production, from mistakes to successes, and help you answer questions your team/company might ask about adopting it.

Video: https://youtu.be/fPzxfeDJDzY

E68309f117985270285ade8082f4877d?s=128

Jake Wharton

May 19, 2017
Tweet

Transcript

  1. 2.

    MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  2. 3.

    MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  3. 4.

    MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  4. 5.

    MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2 @Nullable
  5. 6.

    MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  6. 11.

    TextView.java public float getAlpha() { // Retrieve value... } public

    void setAlpha(float alpha) { // Set value... }
  7. 12.

    TextView.java public float getAlpha() { // Retrieve value... } public

    void setAlpha(float alpha) { // Set value... } TextView tv = // ... Log.d("MainActivity", "Alpha: " + tv.getAlpha()); tv.setAlpha(0f); MainActivity.java
  8. 13.

    TextView.java public float getAlpha() { // Retrieve value... } public

    void setAlpha(float alpha) { // Set value... } MainActivity.kt val tv = // ... Log.d("MainActivity", "Alpha: " + tv.alpha) tv.alpha = 0f
  9. 14.

    TextView.java public float getAlpha() { // Retrieve value... }1 public

    void setAlpha(float alpha) { // Set value... }2 MainActivity.kt val tv = // ... Log.d("MainActivity", "Alpha: " + tv.alpha) tv.alpha = 0f
  10. 15.

    TextView.java public float getAlpha() { // Retrieve value... }1 public

    void setAlpha(float alpha) { // Set value... }2 MainActivity.kt val tv = // ... Log.d("MainActivity", "Alpha: " + tv.alpha) tv.alpha = 0f
  11. 16.

    TextView.java public float getAlpha() { // Retrieve value... }1 public

    void setAlpha(float alpha) { // Set value... }2 MainActivity.kt val tv = // ... Log.d("MainActivity", "Alpha: " + tv.alpha) tv.alpha = 0f
  12. 17.

    MainActivity.java LinearLayout views = // ... for (int i =

    0; i < views.getChildCount(); i++) { View view = views.getChildAt(i); // TODO do something with view }
  13. 18.

    MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }
  14. 19.

    MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }1
  15. 20.

    MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }1
  16. 21.

    MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }
  17. 22.

    MainActivity.kt val views = // ... for (index in 0

    until views.childCount) {Z val view = views.getChildAt(index) // TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3 . Each ->
  18. 23.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3 val = views.getChildAt(i)
  19. 24.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3
  20. 25.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3
  21. 26.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3
  22. 27.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3
  23. 28.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt inline fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3 inline
  24. 29.

    MainActivity.kt val views = // ... views.forEach {Zview -> //

    TODO do something with view }1 ViewGroups.kt inline fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3
  25. 30.

    MainActivity.kt val views = // ... views.forEach {Zview -> /*

    ... */ }1 views.forEachIndexed { index, view -> /* ... */ }1 ViewGroups.kt inline fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3 inline fun ViewGroup.forEachIndexed(action: (Int, View) -> Unit) { for (index in 0 until childCount) { action(index, getChildAt(index)) } } / / T O D O d o s o m e t h i n g w i t h v i e w
  26. 31.

    MainActivity.kt val views = // ... views.forEach {Zview -> /*

    ... */ }1 views.forEachIndexed { index, view -> /* ... */ }1 ViewGroups.kt inline fun ViewGroup.forEach(action: (View) -> Unit) { for (index in 0 until childCount) { action(getChildAt(index)) }2 }3 inline fun ViewGroup.forEachIndexed(action: (Int, View) -> Unit) { for (index in 0 until childCount) { action(index, getChildAt(index)) } } / / T O D O d o s o m e t h i n g w i t h v i e w
  27. 32.

    MainActivity.kt val views = // ... / / T O

    D O d o s o m e t h i n g w i t h v i e w ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index)
  28. 33.

    MainActivity.kt val views = // ... val first = views[0]

    ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) / / T O D O d o s o m e t h i n g w i t h v i e w
  29. 34.

    MainActivity.kt val views = // ... val first = views[0]

    ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) / / T O D O d o s o m e t h i n g w i t h v i e w
  30. 35.

    MainActivity.kt val views = // ... val first = views[0]

    ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) / / T O D O d o s o m e t h i n g w i t h v i e w
  31. 36.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) / / T O D O d o s o m e t h i n g w i t h v i e w
  32. 37.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) / / T O D O d o s o m e t h i n g w i t h v i e w
  33. 38.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) / / T O D O d o s o m e t h i n g w i t h v i e w
  34. 39.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) / / T O D O d o s o m e t h i n g w i t h v i e w
  35. 40.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  36. 41.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  37. 42.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  38. 43.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  39. 44.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  40. 45.

    MainActivity.kt val views = // ... val first = views.get(0)

    views.minusAssign(first) views.plusAssign(first) if (views.contains(first)) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w in
  41. 46.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 / / T O D O d o s o m e t h i n g w i t h v i e w
  42. 47.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() Log.d("MainActivity", "View count: ${views.size}") ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 val ViewGroup.size: Int get() = childCount / / T O D O d o s o m e t h i n g w i t h v i e w
  43. 48.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() Log.d("MainActivity", "View count: ${views.size}") ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 val ViewGroup.size: Int get() = childCount / / T O D O d o s o m e t h i n g w i t h v i e w
  44. 49.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() Log.d("MainActivity", "View count: ${views.size}") ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 val ViewGroup.size: Int get() = childCount / / T O D O d o s o m e t h i n g w i t h v i e w
  45. 50.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() Log.d("MainActivity", "View count: ${views.size}") ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 val ViewGroup.size: Int get() = childCount / / T O D O d o s o m e t h i n g w i t h v i e w
  46. 51.

    MainActivity.kt val views = // ... val first = views[0]

    views -= first views += first if (first in views) doSomething() Log.d("MainActivity", "View count: ${views.size}") ViewGroups.kt operator fun ViewGroup.get(index: Int): View? = getChildAt(index) operator fun ViewGroup.minusAssign(child: View) = removeView(child) operator fun ViewGroup.plusAssign(child: View) = addView(child) operator fun ViewGroup.contains(child: View) = indexOfChild(child) != -1 val ViewGroup.size: Int get() = childCount / / T O D O d o s o m e t h i n g w i t h v i e w
  47. 52.

    MainActivity.kt val views = // ... / / T O

    D O d o s o m e t h i n g w i t h v i e w ViewGroups.kt fun ViewGroup.children() = object : Iterable<View> { override fun iterator() = object : Iterator<View> { var index = 0 override fun hasNext() = index < childCount override fun next() = getChildAt(index++) } }
  48. 53.

    MainActivity.kt val views = // ... for (view in views.children())

    { // TODO do something with view }1 ViewGroups.kt fun ViewGroup.children() = object : Iterable<View> { override fun iterator() = object : Iterator<View> { var index = 0 override fun hasNext() = index < childCount override fun next() = getChildAt(index++) }2 }3 / / T O D O d o s o m e t h i n g w i t h v i e w
  49. 54.

    MainActivity.kt val views = // ... for (view in views.children())

    { // TODO do something with view }1 val visibleHeight = views.children() .filter { it.visibility == View.VISIBLE } .sumBy { it.measuredHeight } ViewGroups.kt fun ViewGroup.children() = object : Iterable<View> { override fun iterator() = object : Iterator<View> { var index = 0 override fun hasNext() = index < childCount override fun next() = getChildAt(index++) }2 }3 / / T O D O d o s o m e t h i n g w i t h v i e w
  50. 55.

    MainActivity.kt val views = // ... for (view in views.children())

    { // TODO do something with view } val visibleHeight = views.children() .filter { it.visibility == View.VISIBLE } .sumBy { it.measuredHeight } ViewGroups.kt fun ViewGroup.children() = object : Iterable<View> { override fun iterator() = object : Iterator<View> { var index = 0 override fun hasNext() = index < childCount override fun next() = getChildAt(index++) } } / / T O D O d o s o m e t h i n g w i t h v i e w
  51. 57.
  52. 58.

    Traces.kt inline fun trace(sectionName: String, body: () -> Unit) {Z

    Trace.beginSection(sectionName) try { body() }2finally { Trace.endSection() }3 }4 MainActivity.kt trace("foo") { expensiveCalculation() }1
  53. 59.

    Traces.kt inline fun <T> trace(sectionName: String, body: () -> T):

    T {Z Trace.beginSection(sectionName) try { return body() }2finally { Trace.endSection() }3 }4 Unit MainActivity.kt trace("foo") { expensiveCalculation() }1 <T> T T return
  54. 60.

    Traces.kt inline fun <T> trace(sectionName: String, body: () -> T):

    T {Z Trace.beginSection(sectionName) try { return body() }2finally { Trace.endSection() }3 }4 MainActivity.kt val result = trace("foo") { expensiveCalculation() }1 val result = <T> T T return
  55. 61.

    Traces.kt inline fun <T> trace(sectionName: String, body: () -> T):

    T {Z Trace.beginSection(sectionName) try { return body() }2finally { Trace.endSection() }3 }4 MainActivity.kt val result = trace("foo") { expensiveCalculation() }1
  56. 62.

    MainActivity.java SQLiteDatabase db = // ... db.beginTransaction(); try { db.delete("users",

    "first_name = ?", new String[] { "jake" }); } finally { db.endTransaction(); }1
  57. 63.

    MainActivity.java SQLiteDatabase db = // ... db.beginTransaction(); try { db.delete("users",

    "first_name = ?", new String[] { "jake" }); db.setTransactionSuccessful(); } finally { db.endTransaction(); }1
  58. 64.

    SQLiteDatabase db = // ... db.beginTransaction(); try { db.delete("users", "first_name

    = ?", new String[] { "jake" }); db.setTransactionSuccessful(); } finally { db.endTransaction(); }1 Databases.kt inline fun SQLiteDatabase.transaction(body: () -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1
  59. 65.

    MainActivity.kt val db = // ... db.transaction {4 db.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: () -> Unit) { beginTransaction() try { body()X setTransactionSuccessful() } finally { endTransaction() }2 }1 1 SQLiteDatabase db.beginTransaction(); try new String[] { } db.setTransactionSuccessful(); finally { db.endTransaction(); }1
  60. 66.

    MainActivity.kt val db = // ... db.transaction {4 db.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: () -> Unit) { beginTransaction() try { body()X setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  61. 67.

    MainActivity.kt val db = // ... db.transaction {4 db.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: () -> Unit) { beginTransaction() try { body()X setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  62. 68.

    MainActivity.kt val db = // ... db.transaction {4 db.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body()X setTransactionSuccessful() } finally { endTransaction() }2 }1 1 SQLiteDatabase
  63. 69.

    MainActivity.kt val db = // ... db.transaction {4 db.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body(this)X setTransactionSuccessful() } finally { endTransaction() }2 }1 1 SQLiteDatabase body(this)X
  64. 70.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body(this) setTransactionSuccessful() } finally { endTransaction() }2 }1 1 it.delete SQLiteDatabase body(this)X
  65. 71.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body(this)F setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  66. 72.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body(this)F setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  67. 73.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: (SQLiteDatabase) -> Unit) { beginTransaction() try { body(this)F setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  68. 74.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.() -> Unit) { beginTransaction() try { body(this)F setTransactionSuccessful() } finally { endTransaction() }2 }1 1 SQLiteDatabase.() -> Unit
  69. 75.

    MainActivity.kt val db = // ... db.transaction {4 it.delete("users", "first_name

    = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.() -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1 1 SQLiteDatabase.() -> Unit body()F
  70. 76.

    it. MainActivity.kt val db = // ... db.transaction {4 delete("users",

    "first_name = ?", arrayOf("jake")) }3 Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.() -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1 1 delete SQLiteDatabase.() -> Unit body()F
  71. 77.

    MainActivity.kt val db = // ... db.transaction {4 delete("users", "first_name

    = ?", arrayOf("jake"))G }3 Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.() -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1 1
  72. 78.

    MainActivity.kt = // ... "jake" Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.()

    -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1 1 class UserPersistence(private val db: SQLiteDatabase) { fun deleteByFirstName(name: String) { db.transaction { delete("users", "first_name = ?", arrayOf(name))G }3 } } UserPersistence.kt
  73. 79.

    MainActivity.kt = // ... "jake" Databases.kt inline fun SQLiteDatabase.transaction(body: SQLiteDatabase.()

    -> Unit) { beginTransaction() try { body() setTransactionSuccessful() } finally { endTransaction() }2 }1 1 class UserPersistence(private val db: SQLiteDatabase) { fun deleteByFirstName(name: String) { db.transaction { delete("users", "first_name = ?", arrayOf(name))G }3 } } UserPersistence.kt
  74. 80.

    class UserPersistence(private val db: SQLiteDatabase) { fun deleteByFirstName(name: String) {

    db.transaction { delete("users", "first_name = ?", arrayOf(name))G }3 }2 }1 UserPersistence.kt
  75. 81.

    class UserPersistence(private val db: SQLiteDatabase) { private val deleteByFirstName =

    db.compileStatement( "DELETE FROM users WHERE first_name = ?") fun deleteByFirstName(name: String) { db.transaction { deleteByFirstName.bindString(1, name) deleteByFirstName.execute() }3 }2 }1 UserPersistence.kt delete(" ", " , arrayOf( ))G
  76. 82.

    sssssssssssss class UserPersistence(private val db: SQLiteDatabase) { private val deleteByFirstName

    = db.compileStatement( "DELETE FROM users WHERE first_name = ?") fun deleteByFirstName(name: String) { db.transaction { deleteByFirstName.bindString(1, name) deleteByFirstName.execute() }3 }2 }1 UserPersistence.kt
  77. 83.

    sssssssssssss class UserPersistence(private val db: SQLiteDatabase) { private val deleteByFirstName

    by lazy { db.compileStatement("DELETE FROM users WHERE first_name = ?") } fun deleteByFirstName(name: String) { db.transaction { deleteByFirstName.bindString(1, name) deleteByFirstName.execute() }3 }2 }1 UserPersistence.kt
  78. 84.

    sssssssssssss class UserPersistence(private val db: SQLiteDatabase) { private val deleteByFirstName

    by lazy { db.compileStatement("DELETE FROM users WHERE first_name = ?") }X fun deleteByFirstName(name: String) { db.transaction { deleteByFirstName.bindString(1, name) deleteByFirstName.execute() }3 }2 }1 UserPersistence.kt
  79. 86.

    private val deleteByFirstName by lazy { db.compileStatement("DELETE FROM users WHERE

    first_name = ?") }X private val name by Delegates.observable("jane") { old, new, prop -> println("Name changed from $old to $new") }
  80. 87.

    private val deleteByFirstName by lazy { db.compileStatement("DELETE FROM users WHERE

    first_name = ?") }X private val name by Delegates.observable("jane") { old, new, prop -> println("Name changed from $old to $new") } private val address by Delegates.notNull<String>()
  81. 88.

    private val deleteByFirstName by lazy { db.compileStatement("DELETE FROM users WHERE

    first_name = ?") }X private val name by Delegates.observable("jane") { old, new, prop -> println("Name changed from $old to $new") } private val address by Delegates.notNull<String>() private val nameView by bindView<TextView>(R.id.name)
  82. 89.

    private val deleteByFirstName by lazy { db.compileStatement("DELETE FROM users WHERE

    first_name = ?") }X private val name by Delegates.observable("jane") { old, new, prop -> println("Name changed from $old to $new") } private val address by Delegates.notNull<String>() private val nameView by bindView<TextView>(R.id.name)
  83. 90.

    class MyListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {

    } override fun onTransitionResume(transition: Transition) { } override fun onTransitionPause(transition: Transition) { } override fun onTransitionCancel(transition: Transition) { } override fun onTransitionStart(transition: Transition) { }Y }X
  84. 92.

    class MyListener : TransitionListener { override fun onTransitionStart(transition: Transition) {

    }Y }X object EmptyTransitionListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionStart(transition: Transition) {} }
  85. 93.

    class MyListener : TransitionListener { override fun onTransitionStart(transition: Transition) {

    }Y }X object EmptyTransitionListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionStart(transition: Transition) {} }
  86. 94.

    class MyListener : TransitionListener {T override fun onTransitionStart(transition: Transition) {

    }Y }X object EmptyTransitionListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionStart(transition: Transition) {} }G
  87. 95.

    class MyListener : TransitionListener by EmptyTransitionListener {T override fun onTransitionStart(transition:

    Transition) { }Y }X object EmptyTransitionListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionStart(transition: Transition) {} }G
  88. 96.

    class MyListener : TransitionListener by EmptyTransitionListener {T override fun onTransitionStart(transition:

    Transition) { }Y }X object EmptyTransitionListener : TransitionListener { override fun onTransitionEnd(transition: Transition) {} override fun onTransitionResume(transition: Transition) {} override fun onTransitionPause(transition: Transition) {} override fun onTransitionCancel(transition: Transition) {} override fun onTransitionStart(transition: Transition) {} }G
  89. 97.

    class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt
  90. 99.

    class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt
  91. 100.

    class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt fun payment(body: PaymentRobot.() -> Unit) = PaymentRobot().apply(body)
  92. 101.

    class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt fun payment(body: PaymentRobot.() -> Unit) = PaymentRobot().apply(body)
  93. 106.

    sealed class Payloads { data class Favorite(val favorited: Boolean) :

    Payloads() data class Retweet(val retweeted: Boolean) : Payloads() }G
  94. 107.

    sealed class Payloads { data class Favorite(val favorited: Boolean) :

    Payloads() data class Retweet(val retweeted: Boolean) : Payloads() data class CountUpdate( val favorites: Long, val retweets: Long, val replies: Long) : Payloads() }G
  95. 111.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited }3 }2 }1
  96. 112.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited }3 }2 }1
  97. 113.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited }3 }2 }1 sealed class Payloads { data class Favorite(val favorited: Boolean) : Payloads() data class Retweet(val retweeted: Boolean) : Payloads() data class CountUpdate( val favorites: Long, val retweets: Long, val replies: Long) : Payloads() }G
  98. 114.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited }3 }2 }1
  99. 115.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited is Retweet -> holder.retweetIcon.isActivated = it.retweeted }3 }2 }1
  100. 116.

    override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { payloads.forEach

    { when (it) { is Favorite -> holder.favoriteIcon.isActivated = it.favorited is Retweet -> holder.retweetIcon.isActivated = it.retweeted is CountUpdate -> { holder.apply { favoriteCount.text = it.favorites.toString() retweetCount.text = it.retweets.toString() replyCount.text = it.replies.toString() }5 }4 }3 }2 }1
  101. 117.
  102. 118.

    It takes great salesmanship to convince a customer to buy

    something from you that isn't built or isn't finished. Fred Wilson
  103. 119.
  104. 120.
  105. 126.

    Never doubt that a small group of thoughtful, committed citizens

    can change the world; indeed,
 it's the only thing 
 that ever has. Margaret Mead (Def. not talking about tech)
  106. 131.

    One of the most feared expressions in modern times is

    'The computer is down.' Norman Ralph Augustine
  107. 132.
  108. 133.

    Jake Wharton @JakeWharton Type systems are a form of tests.

    I declare an expected type and the tests (aka compiler) validates the actual ones. 6:43 PM - 11 Jan 2017 74 Follow 16
  109. 134.
  110. 136.

    Ellen Shapiro @designatednerd My style: “I’m the idiot who went

    down the rabbit hole first, and I’m here to tell you which path leads to fluffy bunnies vs. angry moles.” 14 Mar Ellen Shapiro @designatednerd My favorite bit of any talk I give is talking about the dumb shit I did so the audience doesn’t do it. Makes the hair pulled out worth it. 4:56 PM - 14 Mar 2017 1 Follow
  111. 138.
  112. 139.
  113. 142.
  114. 143.
  115. 144.

    What’s next? Kotlin documentation and koans https://kotlinlang.org/ Android Kotlin documentation

    https://developer.android.com/kotlin/index.html Kotlin In Action Dimitry Jemerov, Svetlana Isakova
  116. 146.