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

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

54879f243e5b72eedb2d379bed6fda27?s=128

Jake Wharton
PRO

May 19, 2017
Tweet

More Decks by Jake Wharton

Other Decks in Programming

Transcript

  1. +Christina Lee @RunChristinaRun +Jake Wharton @JakeWharton Kotlin is here Life

    is great and everything will be OK
  2. MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  3. MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  4. MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  5. MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2 @Nullable
  6. MainActivity.java public class MainActivity extends Activity { @Override protected void

    onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); }1 }2
  7. MainActivity.kt class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) }1 }2
  8. MainActivity.kt class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) }1 }2
  9. MainActivity.kt class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) }1 }2
  10. TextView.java public float getAlpha() { // Retrieve value... }

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

    void setAlpha(float alpha) { // Set value... }
  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
  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
  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
  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
  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
  17. MainActivity.java LinearLayout views = // ... for (int i =

    0; i < views.getChildCount(); i++) { View view = views.getChildAt(i); // TODO do something with view }
  18. MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }
  19. MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }1
  20. MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }1
  21. MainActivity.kt val views = // ... for (index in 0

    until views.childCount) { val view = views.getChildAt(index) // TODO do something with view }
  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 ->
  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)
  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
  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
  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
  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
  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
  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
  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
  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
  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)
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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++) } }
  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
  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
  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
  56. MainActivity.java Trace.beginSection(sectionName); expensiveCalculation(); Trace.endSection();

  57. MainActivity.java Trace.beginSection(sectionName); expensiveCalculation(); Trace.endSection(); Traces.kt inline fun trace(sectionName: String, body:

    () -> Unit) { Trace.beginSection(sectionName) try { body() }2finally { Trace.endSection() }3 }4
  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
  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
  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
  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
  62. MainActivity.java SQLiteDatabase db = // ... db.beginTransaction(); try { db.delete("users",

    "first_name = ?", new String[] { "jake" }); } finally { db.endTransaction(); }1
  63. MainActivity.java SQLiteDatabase db = // ... db.beginTransaction(); try { db.delete("users",

    "first_name = ?", new String[] { "jake" }); db.setTransactionSuccessful(); } finally { db.endTransaction(); }1
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  85. private val deleteByFirstName by lazy { db.compileStatement("DELETE FROM users WHERE

    first_name = ?") }X
  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") }
  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>()
  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)
  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)
  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
  91. class MyListener : TransitionListener { override fun onTransitionStart(transition: Transition) {

    }Y }X
  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) {} }
  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) {} }
  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
  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
  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
  97. class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt
  98. @Test fun sendMoney() { PaymentRobot().apply { amount(4_00) recipient("foo@example.com") send() }

    } PaymentTest.kt
  99. class PaymentRobot { fun amount(value: Long) { // TODO Espresso

    interactions } fun recipient(value: String) { // TODO Espresso interactions } fun send() { // TODO Espresso interactions } } PaymentRobot.kt
  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)
  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)
  102. @Test fun sendMoney() { PaymentRobot().apply {T amount(4_00) recipient("foo@example.com") send() }T

    }G PaymentTest.kt p
  103. @Test fun sendMoney() { payment {T amount(4_00) recipient("foo@example.com") send() }T

    }G PaymentTest.kt
  104. sealed class Payloads { }G

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

    Payloads() }G
  106. sealed class Payloads { data class Favorite(val favorited: Boolean) :

    Payloads() data class Retweet(val retweeted: Boolean) : Payloads() }G
  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
  108. override fun onBindViewHolder(holder: TweetViewHolder, position: Int, payloads: List<Any>) { }1

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

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

    { when (it) { }3 }2 }1
  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
  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
  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
  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
  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
  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
  117. None
  118. It takes great salesmanship to convince a customer to buy

    something from you that isn't built or isn't finished. Fred Wilson
  119. None
  120. None
  121. Step 3 Step 2 Step 1

  122. Step 1 Step 3 You Step 2

  123. Step 3 Management Step 2 Step 1

  124. Team Step 3 Step 2 Step 1

  125. You Get excited.

  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)
  127. Be enthusiastic

  128. Adoption is work. If you want it, you need to

    earn it.
  129. Management Be persuasive.

  130. I call it my billion- dollar mistake. Sir Charles Antony

    Richard Hoare
  131. One of the most feared expressions in modern times is

    'The computer is down.' Norman Ralph Augustine
  132. None
  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
  134. None
  135. Team Do the work.

  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
  137. Define success

  138. None
  139. None
  140. http://blog.danlew.net/

  141. On-boarding should be a first class citizen

  142. Show up

  143. None
  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
  145. +Christina Lee @RunChristinaRun #KotlinIsHere Thank you! +Jake Wharton @JakeWharton

  146. None