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

Help Kotlin Help You

Caren
August 13, 2019

Help Kotlin Help You

Caren

August 13, 2019
Tweet

More Decks by Caren

Other Decks in Education

Transcript

  1. Help otlin Help You
    @calren24

    View Slide

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

    View Slide

  3. Data classes

    Nullability

    Scope functions

    Coroutines

    Dangers of synthetic binding

    View Slide

  4. Data classes

    View Slide

  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() { … }
    }

    View Slide

  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() { … }
    }

    View Slide

  7. • Maintaining data classes can be a hassle

    View Slide

  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ë”);

    View Slide

  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ë”);
    ??? ???

    View Slide

  10. View Slide

  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() { … }
    }

    View Slide

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

    View Slide

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

    View Slide

  14. • Automatically creates equals() , hashCode(), toString()

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

    View Slide

  15. • Automatically creates equals() , hashCode(), toString()

    • val vs var

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

    View Slide

  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)

    View Slide

  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
    )

    View Slide

  18. Nullability

    View Slide

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

    View Slide

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

    be wary of silent failures using ? 


    View Slide

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

    be wary of silent failures using ? 

    user?.paymentMethod?.executeTransaction()

    View Slide

  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”)

    View Slide

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

    View Slide

  24. // Java-like
    if (userDroid.emailAddress != null && userDroid.optIntoEmails) {
    sendMarketingEmail(userDroid.emailAddress!!)
    }
    // Kotlin-esque
    userDroid.emailAddress?.
    takeIf { userDroid.optIntoEmails }?.
    let { sendMarketingEmail(it) }

    View Slide

  25. Scope Functions

    View Slide

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

    Scope Functions

    View Slide

  27. Functions that allow for changing ‘scope’ of variables

    user?.fullName?.let { fullName ->
    val formattedName = format(fullName)
    displayGreeting(formattedName)
    }
    Scope Functions

    View Slide

  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

    View Slide

  29. Scope Functions
    From Medium article: Kotlin Demystified - Scope Functions

    View Slide

  30. let { }

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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 { }

    View Slide

  36. apply { }

    View Slide

  37. apply { }
    Useful for object configuration

    View Slide

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

    View Slide

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

    View Slide

  40. also { }
    Useful for calls that need a contextual object, but doesn’t alter
    the object itself

    View Slide

  41. also { }
    val paint = Paint()
    .apply {
    color = Color.BLUE
    pathEffect = PathEffect()
    }
    .also {
    print("Starting paint with ${it.color}")
    }

    View Slide

  42. run { }

    View Slide

  43. run { }
    Combination of with and let

    View Slide

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

    View Slide

  45. run { }
    val randomWelcomeGreeting =
    GreetingGenerator.obtain().run {
    day = getDayOfWeek()
    mood = Mood.Cheerful
    voice = Voice.OPRAH
    generate()
    }

    View Slide

  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

    View Slide

  47. Kotlin Standard Functions Cheat Sheet

    View Slide

  48. Coroutines

    View Slide

  49. Simplify managing background threads without managing
    callbacks

    View Slide

  50. Simplify managing background threads without managing
    callbacks

    Sequential code is a lot easier to read and manage

    View Slide

  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
    }
    }

    View Slide

  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

    View Slide

  53. Synthetic Binding

    View Slide

  54. import
    kotlinx.android.synthetic.main.
    activity_main.*


    button.text = "Click me"
    android:id="@+id/button"/>
    Activity.kt activity.xml

    View Slide

  55. import
    kotlinx.android.synthetic.main.
    activity_main.*


    button.text = "Click me"
    android:id="@+id/button"/>
    Activity.kt activity.xml
    Makes available ALL ids defined in the project

    View Slide

  56. import
    kotlinx.android.synthetic.main.
    activity_main.*


    button.text = "Click me"
    android:id="@+id/button"/>
    Activity.kt activity.xml
    Makes available ALL ids defined in the project

    Views unrelated to inflated layout are accessible

    View Slide

  57. import
    kotlinx.android.synthetic.main.
    activity_main.*


    button.text = "Click me"
    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

    View Slide

  58. import
    kotlinx.android.synthetic.main.
    activity_main.*


    button.text = "Click me"
    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

    View Slide

  59. Codelabs

    View Slide

  60. Refactoring to Kotlin

    Using Kotlin Coroutines in your Android app

    Android Data Binding

    Room with a View

    View Slide