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

Help Kotlin Help You

7bf2baf0d8d5d7d96e6b67c5d567e3f9?s=47 Caren
August 13, 2019

Help Kotlin Help You

7bf2baf0d8d5d7d96e6b67c5d567e3f9?s=128

Caren

August 13, 2019
Tweet

Transcript

  1. Help otlin Help You @calren24

  2. An ‘early’ taste of Kotlin: from Kotlin in Action

  3. Data classes Nullability Scope functions Coroutines Dangers of synthetic binding

  4. Data classes

  5. public class User { private String name; @Nullable private String

    emailAddress; public User(String name) { … } public User(String name, String emailAddress) { … } public String getName() { … } public void setName(String name) { … } @Nullable public String getEmailAddress() { … } public void setEmailAddress(@Nullable String emailAddress) { … } @Override public String toString() { … } @Override public boolean equals(Object o) { … } @Override public int hashCode() { … } }
  6. public class User { private String name; @Nullable private String

    emailAddress; public User(String name) { … } public User(String name, String emailAddress) { … } public String getName() { … } public void setName(String name) { … } @Nullable public String getEmailAddress() { … } public void setEmailAddress(@Nullable String emailAddress) { … } @Override public String toString() { … } @Override public boolean equals(Object o) { … } @Override public int hashCode() { … } }
  7. • Maintaining data classes can be a hassle

  8. • Maintaining data classes can be a hassle • Creating

    objects can be confusing if builder pattern doesn’t exist
 
 new Book("Jane Eyre", "Charlotte Brontë”);
  9. • Maintaining data classes can be a hassle • Creating

    objects can be confusing if builder pattern doesn’t exist
 
 new Book("Jane Eyre", "Charlotte Brontë”); ??? ???
  10. None
  11. public class User { private String name; @Nullable private String

    emailAddress; public User(String name) { … } public User(String name, String emailAddress) { … } public String getName() { … } public void setName(String name) { … } @Nullable public String getEmailAddress() { … } public void setEmailAddress(@Nullable String emailAddress) { … } @Override public String toString() { … } @Override public boolean equals(Object o) { … } @Override public int hashCode() { … } }
  12. data class User (val name: String, var emailAddress: String? =

    null)
  13. data class User (val name: String, var emailAddress: String? =

    null)
  14. • Automatically creates equals() , hashCode(), toString()
 data class User

    (val name: String, var emailAddress: String? = null)
  15. • Automatically creates equals() , hashCode(), toString() • val vs

    var
 data class User (val name: String, var emailAddress: String? = null)
  16. • Automatically creates equals() , hashCode(), toString() • val vs

    var • denotes nullable fields
 
 val userDroid = User(name = "Droid")
 data class User (val name: String, var emailAddress: String? = null)
  17. • Automatically creates equals() , hashCode(), toString() • val vs

    var • denotes nullable fields
 
 val userDroid = User(name = "Droid") • default values
 data class User( val name: String, var emailAddress: String? = null, var optIntoEmails: Boolean = true )
  18. Nullability

  19. !! usually signals a code smell and is not as

    safe as you think
  20. !! usually signals a code smell and is not as

    safe as you think be wary of silent failures using ? 

  21. !! usually signals a code smell and is not as

    safe as you think be wary of silent failures using ? 
 user?.paymentMethod?.executeTransaction()
  22. !! usually signals a code smell and is not as

    safe as you think be wary of silent failures using ? 
 user?.paymentMethod?.executeTransaction() ?: Log.i("TAG", “No payment method stored”)
  23. // Java-like if (userDroid.emailAddress != null && userDroid.optIntoEmails) { sendMarketingEmail(userDroid.emailAddress!!)

    }
  24. // Java-like if (userDroid.emailAddress != null && userDroid.optIntoEmails) { sendMarketingEmail(userDroid.emailAddress!!)

    } // Kotlin-esque userDroid.emailAddress?. takeIf { userDroid.optIntoEmails }?. let { sendMarketingEmail(it) }
  25. Scope Functions

  26. Functions that allow for changing ‘scope’ of variables Scope Functions

  27. Functions that allow for changing ‘scope’ of variables user?.fullName?.let {

    fullName -> val formattedName = format(fullName) displayGreeting(formattedName) } Scope Functions
  28. Functions that allow for changing ‘scope’ of variables also {

    } apply { } let { } run { } with("an argument") { doSomething(this) } Similar in functionality, differences in appropriate use case Scope Functions
  29. Scope Functions From Medium article: Kotlin Demystified - Scope Functions

  30. let { }

  31. let { } Useful for null check and self-contained variables

  32. if (user != null && user.emailAddress != null) { sendMarketingEmail(user.emailAddress!!)

    } let { }
  33. if (user != null && user.emailAddress != null) { sendMarketingEmail(user.emailAddress!!)

    } user?.emailAddress?.let { sendMarketingEmail(it) } let { }
  34. if (user != null && user.emailAddress != null) { sendMarketingEmail(user.emailAddress!!)

    } user?.emailAddress?.let { sendMarketingEmail(it) } user?.emailAddress?.let { emailAddress -> sendMarketingEmail(emailAddress) } let { }
  35. if (user != null && user.emailAddress != null) { sendMarketingEmail(user.emailAddress!!)

    } user?.emailAddress?.let { sendMarketingEmail(it) } user?.emailAddress?.let { emailAddress -> sendMarketingEmail(emailAddress) } Database.getConnection().let { } // connection doesn't exist outside let { }
  36. apply { }

  37. apply { } Useful for object configuration

  38. val view = View(this).apply { setBackgroundColor() setOnLongClickListener { } setOnClickListener

    { } } apply { }
  39. val view = View(this).apply { setBackgroundColor() setOnLongClickListener { } setOnClickListener

    { } } val view2 = View(this) view2.setBackgroundColor() view2.setOnLongClickListener { } view2.setOnLongClickListener { } apply { }
  40. also { } Useful for calls that need a contextual

    object, but doesn’t alter the object itself
  41. also { } val paint = Paint() .apply { color

    = Color.BLUE pathEffect = PathEffect() } .also { print("Starting paint with ${it.color}") }
  42. run { }

  43. run { } Combination of with and let

  44. run { } Combination of with and let Useful for

    initialization
  45. run { } val randomWelcomeGreeting = GreetingGenerator.obtain().run { day =

    getDayOfWeek() mood = Mood.Cheerful voice = Voice.OPRAH generate() }
  46. Scope Functions let Executing code with null check 
 Introducing

    local variables apply Object configuration
 run Top level initialization also Additional effects with Grouping function calls
  47. Kotlin Standard Functions Cheat Sheet

  48. Coroutines

  49. Simplify managing background threads without managing callbacks

  50. Simplify managing background threads without managing callbacks Sequential code is

    a lot easier to read and manage
  51. Simplify managing background threads without managing callbacks Sequential code is

    a lot easier to read and manage
 
 // Async callbacks networkRequest { result -> // Successful network request databaseSave(result) { rows -> // Result saved } }
  52. Simplify managing background threads without managing callbacks Sequential code is

    a lot easier to read and manage
 
 // Async callbacks networkRequest { result -> // Successful network request databaseSave(result) { rows -> // Result saved } } // The same code with coroutines val result = networkRequest() // Successful network request databaseSave(result) // Result saved vs
  53. Synthetic Binding

  54. import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" <TextView 


    android:id="@+id/button"/> Activity.kt activity.xml
  55. import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" <TextView 


    android:id="@+id/button"/> Activity.kt activity.xml Makes available ALL ids defined in the project
  56. import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" <TextView 


    android:id="@+id/button"/> Activity.kt activity.xml Makes available ALL ids defined in the project Views unrelated to inflated layout are accessible
  57. import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" <TextView 


    android:id="@+id/button"/> Activity.kt activity.xml Makes available ALL ids defined in the project Views unrelated to inflated layout are accessible Doesn’t expose nullability well
  58. import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" <TextView 


    android:id="@+id/button"/> Activity.kt activity.xml Makes available ALL ids defined in the project Views unrelated to inflated layout are accessible Doesn’t expose nullability well Other options: Data Binding or Butter Knife
  59. Codelabs

  60. Refactoring to Kotlin Using Kotlin Coroutines in your Android app

    Android Data Binding Room with a View