Slide 1

Slide 1 text

Help otlin Help You @calren24

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

Data classes Nullability Scope functions Coroutines Dangers of synthetic binding

Slide 4

Slide 4 text

Data classes

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

• Maintaining data classes can be a hassle

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Nullability

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

!! usually signals a code smell and is not as safe as you think be wary of silent failures using ? 


Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

Scope Functions

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Scope Functions From Medium article: Kotlin Demystified - Scope Functions

Slide 30

Slide 30 text

let { }

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

apply { }

Slide 37

Slide 37 text

apply { } Useful for object configuration

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

run { }

Slide 43

Slide 43 text

run { } Combination of with and let

Slide 44

Slide 44 text

run { } Combination of with and let Useful for initialization

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

Kotlin Standard Functions Cheat Sheet

Slide 48

Slide 48 text

Coroutines

Slide 49

Slide 49 text

Simplify managing background threads without managing callbacks

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

Synthetic Binding

Slide 54

Slide 54 text

import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" Activity.kt activity.xml

Slide 55

Slide 55 text

import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" Activity.kt activity.xml Makes available ALL ids defined in the project

Slide 56

Slide 56 text

import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" Activity.kt activity.xml Makes available ALL ids defined in the project Views unrelated to inflated layout are accessible

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

import kotlinx.android.synthetic.main. activity_main.*
 
 button.text = "Click me" 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

Slide 59

Slide 59 text

Codelabs

Slide 60

Slide 60 text

Refactoring to Kotlin Using Kotlin Coroutines in your Android app Android Data Binding Room with a View