You can do better with Kotlin Svetlana Isakova Kotlin Programming - - PowerPoint PPT Presentation

you can do better with kotlin
SMART_READER_LITE
LIVE PREVIEW

You can do better with Kotlin Svetlana Isakova Kotlin Programming - - PowerPoint PPT Presentation

You can do better with Kotlin Svetlana Isakova Kotlin Programming Language - modern - pragmatic - Android-friendly Official on Android Not only Android Pragmatic - tooling - Java interop From has good tooling - completion - navigation -


slide-1
SLIDE 1

Svetlana Isakova

You can do better with Kotlin

slide-2
SLIDE 2
  • modern
  • pragmatic
  • Android-friendly

Kotlin Programming Language

slide-3
SLIDE 3

Official on Android

slide-4
SLIDE 4

Not only Android

slide-5
SLIDE 5

Pragmatic

  • tooling
  • Java interop
slide-6
SLIDE 6

From

slide-7
SLIDE 7

has good tooling

slide-8
SLIDE 8
  • completion
  • navigation
  • refactorings
  • inspections

slide-9
SLIDE 9

can be easily mixed with Java code

slide-10
SLIDE 10

*.java *.class *.dex

compiled to Java bytecode

*.kt

slide-11
SLIDE 11

Kotlin code Java code

You can have Java & Kotlin code in one project

slide-12
SLIDE 12

You can gradually add Kotlin to your existing app

slide-13
SLIDE 13

Android-friendly

slide-14
SLIDE 14

Android Studio is based on IntelliJ IDEA

slide-15
SLIDE 15

just another library for your app

rxjava-2.1.2 kotlin-stdlib-1.1.4

6315 10212

slide-16
SLIDE 16

No Kotlin SDK

…just JDK + extensions

small runtime jar easy Java interop

slide-17
SLIDE 17

Modern

  • concise
  • safe
  • expressive
slide-18
SLIDE 18

concise

slide-19
SLIDE 19

public class Person {
 private final String name;
 private final int age;
 
 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }
 
 public String getName() {
 return name;
 }
 
 public int getAge() {
 return age;
 }
 }

slide-20
SLIDE 20
  • equals
  • hashCode
  • toString

data

class Person(val name: String, val age: Int)

slide-21
SLIDE 21

public class Person {
 private final String name;
 private final int age;
 
 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }
 
 public String getName() {
 return name;
 }
 
 public int getAge() {
 return age;
 }
 }

class Person( val name: String, val age: Int ) person.name person.getName()

slide-22
SLIDE 22

class Person( val name: String, val age: Int ) person.getName()

slide-23
SLIDE 23

public class Person {
 private final String name;
 private final int age;
 
 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }
 
 public String getName() {
 return name;
 }
 
 public int getAge() {
 return age;
 }
 }

person.name

slide-24
SLIDE 24

public void updateWeather(int degrees) {
 String description;
 Colour colour;
 if (degrees < 5) {
 description = "cold";
 colour = BLUE;
 } else if (degrees < 23) {
 description = "mild";
 colour = ORANGE;
 } else {
 description = "hot";
 colour = RED;
 }
 // ...
 }

enum Colour { BLUE, ORANGE, RED, /*...*/; }

slide-25
SLIDE 25

fun updateWeather(degrees: Int) {
 val description: String
 val colour: Colour
 if (degrees < 5) {
 description = "cold"
 colour = BLUE
 } else if (degrees < 23) {
 description = "mild"
 colour = ORANGE
 } else {
 description = "hot"
 colour = RED
 }
 // ...
 }

slide-26
SLIDE 26

fun updateWeather(degrees: Int) {
 val (description: String, colour: Colour) =
 if (degrees < 5) {
 Pair("cold", BLUE)
 } else if (degrees < 23) {
 Pair("mild", ORANGE)
 } else {
 Pair("hot", RED)
 } // ...
 }

slide-27
SLIDE 27

fun updateWeather(degrees: Int) {
 val (description, colour) =
 if (degrees < 5) {
 Pair("cold", BLUE)
 } else if (degrees < 23) {
 Pair("mild", ORANGE)
 } else {
 Pair("hot", RED)
 } // ...
 }

slide-28
SLIDE 28

fun updateWeather(degrees: Int) {
 val (description, colour) = when {
 degrees < 5 -> Pair("cold", BLUE)
 degrees < 23 -> Pair("mild", ORANGE)
 else -> Pair("hot", RED)
 } // ...
 }

slide-29
SLIDE 29

fun updateWeather(degrees: Int) {
 val (description, colour) = when {
 degrees < 5 -> "cold" to BLUE
 degrees < 23 -> "mild" to ORANGE
 else -> "hot" to RED
 }
 }

slide-30
SLIDE 30

val (description, colour) = when {
 degrees < 5 -> "cold" to BLUE
 degrees < 23 -> "mild" to ORANGE
 else -> "hot" to RED
 } String description;
 Colour colour; if (degrees < 5) {
 description = "cold";
 colour = BLUE;
 } else if (degrees < 23) {
 description = "mild";
 colour = ORANGE;
 } else {
 description = "hot";
 colour = RED;
 }

slide-31
SLIDE 31

safe

slide-32
SLIDE 32

Billion Dollar Mistake

slide-33
SLIDE 33

Modern approach: to make NPE compile-time error, not run-time error

slide-34
SLIDE 34

Nullable types in Kotlin

val s1: String = "always not null" 
 val s2: String? = null s1.length

✓ ✗

s2.length "can be null or non-null" null

slide-35
SLIDE 35

val s: String? if (s != null) {
 s.length
 }

Dealing with Nullable Types

slide-36
SLIDE 36

s?.length val s: String?

Dealing with Nullable Types

slide-37
SLIDE 37

val length = if (s != null) s.length else null val s: String?

Nullability operators

val length = s?.length

slide-38
SLIDE 38

val length = if (s != null) s.length else 0 val s: String?

Nullability operators

val length = s?.length ?: 0

slide-39
SLIDE 39

val s: String? if (s == null) fail()
 s.length

Control-flow analysis

slide-40
SLIDE 40

val s: String?

Making NPE explicit

s!!

throws NPE if s is null

s!!.length

slide-41
SLIDE 41

Nullable Types Under the Hood

No performance overhead

@Nullable, @NotNull annotations

slide-42
SLIDE 42

class Optional<T>(val value: T) { 
 fun isPresent() = value != null
 
 fun get() = value ?:
 throw NoSuchElementException("No value present")
 }

Nullable types ≠ Optional

slide-43
SLIDE 43

Annotate your Java types in Kotlin

Type

behaves like regular Java type

@Nullable @NotNull Type Type? Type Type

@ParametersAreNonnullByDefault @MyNonnullApi

Type/Type?

slide-44
SLIDE 44

expressive

slide-45
SLIDE 45

you can avoid any repetition you can make the code look nicer you can create API looking like DSL

expressive

slide-46
SLIDE 46

Kotlin Coroutines

slide-47
SLIDE 47

Kotlin Coroutines

  • the key new feature in Kotlin 1.1
  • simplify asynchronous programming
slide-48
SLIDE 48

Coroutine

a main routine and a subroutine vs coroutines, which call on each other

  • the term from 1960s
  • was used in “The Art of Computer Programming”

by Donald Knuth

slide-49
SLIDE 49

Motivation: async/await

slide-50
SLIDE 50

Motivation

time consuming

  • peration

val image = loadImage(url) setImage(image)

slide-51
SLIDE 51

Solution 1: callbacks

loadImageAsync().whenComplete { image -> runOnUiThread { setImage(image) } }

slide-52
SLIDE 52

Solution 2: async/await

async(UI) { val image = loadImageAsync(url).await() setImage(image) }

slide-53
SLIDE 53

val image = loadImageAsync(url).await() setImage(image) val image = loadImage(url) setImage(image)

No callbacks!

slide-54
SLIDE 54

C# way

async Task ProcessImage(String url) { var image = await LoadImage(url); SetImage(image); }

Kotlin way

fun processImage() = async { val image = loadImageAsync().await() setImage(image) }

slide-55
SLIDE 55

coroutines async/await Language Library

async/await - functions defined in the standard library

slide-56
SLIDE 56

Threads & Coroutines

slide-57
SLIDE 57

Coroutine is similar to a thread

Thread:

  • a sequence of instructions

Multiple threads:

  • can be executed concurrently
  • share resources such as memory

Coroutine: coroutines:

slide-58
SLIDE 58

Coroutine = “lightweight thread”

Thread Coroutine

slide-59
SLIDE 59

Coroutine

computation that can be suspended

computation thread

slide-60
SLIDE 60

Coroutine

computation that can be suspended

slide-61
SLIDE 61

Why suspend?

slide-62
SLIDE 62

Asynchronous computations: how?

slide-63
SLIDE 63

New thread for every computation

simple & straightforward, but too expensive

slide-64
SLIDE 64

Executor

  • fixed number
  • f threads
  • adding tasks
  • but: difficult to manage

dependencies

slide-65
SLIDE 65

Example: waiting for two asynchronous computations to complete

slide-66
SLIDE 66

thenCombine / zip

CompletableFutures / RxJava: managing dependencies the rest of computation in a callback

slide-67
SLIDE 67

Stepping back: what’s wrong with blocking thread?

idle

too expensive

slide-68
SLIDE 68

Stepping back: what’s wrong with blocking UI thread?

blocked

user is blocked

UI

slide-69
SLIDE 69

1 2 3

  • computation that can

be suspended

  • thread is not blocked!

Coroutines

slide-70
SLIDE 70

1 2 3

  • computation that can

be suspended

  • thread is not blocked!

UI UI UI

Coroutines

slide-71
SLIDE 71

suspend function computation that can be suspended

slide-72
SLIDE 72

fun loadImageAsync() = async { /* do the work */ } fun processImage() = async { val image = loadImageAsync().await() setImage(image) }

Back to image example

slide-73
SLIDE 73

async starts new computation

fun loadImageAsync() = async { /* do the work */ }

loadImageAsync

slide-74
SLIDE 74

suspending call

fun processImage() = async { val image = loadImageAsync().await() setImage(image) }

await suspends computation

slide-75
SLIDE 75

fun loadImageAsync(): Deferred<Image> = async { /* do the work */ } interface Deferred<out T> {
 suspend fun await(): T
 }

await is a suspend function

slide-76
SLIDE 76

await suspends computation

fun processImage() = async { val image = loadImageAsync().await() setImage(image) }

slide-77
SLIDE 77

fun processImage() = async { val deferred = loadImageAsync() val image = deferred.await() setImage(image) }

await suspends computation

slide-78
SLIDE 78

await suspends computation

processImage loadImageAsync

1

fun processImage() = async { val deferred = loadImageAsync() val image = deferred.await() setImage(image) }

slide-79
SLIDE 79

await suspends computation

processImage loadImageAsync

1

loadImageAsync processImage

2

await

fun processImage() = async { val deferred = loadImageAsync() val image = deferred.await() setImage(image) }

slide-80
SLIDE 80

await suspends computation

loadImageAsync processImage

2

loadImageAsync processImage

3

…and continues it when result is ready

fun processImage() = async { val deferred = loadImageAsync() val image = deferred.await() setImage(image) }

slide-81
SLIDE 81

await suspends computation

loadImageAsync processImage

2

loadImageAsync processImage

3

…and continues it when result is ready

On which thread?

slide-82
SLIDE 82

Q: On which thread can the coroutine be continued? A: You specify that.

slide-83
SLIDE 83

Continue in any thread from thread pool

async(CommonPool) {
 ...
 }

1 2 3 3

slide-84
SLIDE 84

Continue in the UI thread

1 2 3

async(UI) { ... }

UI UI UI

slide-85
SLIDE 85

Custom executor

async(CustomContext) {
 ...
 }

You can launch coroutine in the custom executor

slide-86
SLIDE 86

1 2 3

fun overlay(first: Image, second: Image): Image fun overlayAsync() = async(CommonPool) {
 val first = loadImageAsync("green")
 val second = loadImageAsync("red")


  • verlay(first.await(), second.await())


}

Two asynchronous computations

  • verlayAsync
  • verlayAsync
  • verlayAsync
slide-87
SLIDE 87

Programming with suspend functions

slide-88
SLIDE 88

Q: Can I define my custom suspend functions? A: Yes.

slide-89
SLIDE 89

Example: simple consecutive logic

fun login(credentials: Credentials): UserID fun loadUserData(userID: UserID): UserData fun showData(data: UserData) fun showUserInfo(cred: Credentials) { val userID = login(credentials) val userData = loadUserData(userID) showData(userData) }

slide-90
SLIDE 90

Rewrite with async/await

fun login(credentials: Credentials): Deferred<UserID> fun loadUserData(userID: UserID): Deferred<UserData> fun showData(data: UserData)

fun showUserInfo(credentials: Credentials) = async(CommonPool) { val userID = login(credentials).await() val userData = loadUserData(userID).await() showData(userData) }

slide-91
SLIDE 91

Rewrite with suspend functions

suspend fun login(credentials: Credentials): UserID suspend fun loadUserData(userID: UserID): UserData fun showData(data: UserData) suspend fun showUserInfo(credentials: Credentials) { val userID = login(credentials) val userData = loadUserData(userID) showData(userData) }

slide-92
SLIDE 92

RxJava / CompletableFuture vs Coroutines

slide-93
SLIDE 93

Rewrite with CompletableFuture

fun loginAsync(credentials: Credentials): CompletableFuture<UserID> fun loadUserDataAsync(userID: UserID): CompletableFuture<UserData> fun showData(data: UserData)

fun showUserInfo(credentials: Credentials) { loginAsync(credentials) .thenCompose { loadUserDataAsync(it) } .thenAccept { showData(it) } }

slide-94
SLIDE 94

Rewrite with RxJava

fun login(credentials: Credentials): Single<UserID> fun loadUserData(userID: UserID): Single<UserData> fun showData(data: UserData)

fun showUserInfo(credentials: Credentials) { login(credentials) .flatMap { loadUserData(it) } .doOnSuccess { showData(it) } .subscribe() }

slide-95
SLIDE 95

“Observables are great, but in many cases they’re kind of overkill.”

somewhere on the Internet

slide-96
SLIDE 96

Kotlin coroutines Reactive Streams

RxJava & coroutines

slide-97
SLIDE 97
slide-98
SLIDE 98

coroutines async/await Language Library channels actors

kotlinx.coroutines

yield

slide-99
SLIDE 99

Experimental status of Coroutines

  • We want the community to try it!
  • Migration aids will be provided
  • Old code will continue to work

via the support library

slide-100
SLIDE 100

kotlinx.coroutines

  • https://github.com/Kotlin/kotlinx.coroutines/
  • Guide to kotlinx.coroutines by example
  • by Roman Elizarov (@relizarov)
slide-101
SLIDE 101
slide-102
SLIDE 102

kotlinlang.org

slide-103
SLIDE 103

Gradle & Kotlin

Writing Gradle build scripts and plugins in Kotlin

slide-104
SLIDE 104

try.kotlinlang.org

slide-105
SLIDE 105

Kotlin Koans

slide-106
SLIDE 106
slide-107
SLIDE 107
  • Basics
  • j2k converter
  • functions, variables
  • control structures (if, when, for, while)
  • try/catch & exceptions
  • Object-oriented programming
  • classes, interfaces
  • data classes
  • objects
  • class objects
  • class delegation
  • extension functions
  • Functional programming
  • lambdas
  • working with collections in a functional style (filter, map, etc.)
  • inlining
  • difference between collections & sequences
  • anonymous functions (return in lambda vs return in anonymous function)
  • Nullability
  • nullable types
  • special operators (?., ?:, !!)
  • let function
  • lateinit modifier
  • Java interoperability
  • Kotlin type hierarchy (Nothing, Any?, etc.)
  • correspondence between Kotlin and Java types
  • platform types for nullability (Int!)
  • collections hierarchy (read-only / mutable list vs java.util.List)
  • platform types for collections ((Mutable)List<Int!>)
  • annotations (@JvmName, @JvmOverloads, @Throws, @JvmStatic)
  • Asynchronous programming
  • async/await
  • coroutines & suspend functions
  • Building DSLs
  • lambdas with receiver
  • with, apply, run functions
  • builders pattern (HTML builders)
  • Conventions
  • operator overloading (a + b, a < b)
  • others (e in set, map[key], first..last, val (a, b) = pair)
  • delegated properties (val prop by lazy { ... })
  • Generics
  • reified type parameters
  • basic intro to covariance / contravariance

1 . T h e K

  • t

l i n c

  • d

e i s c

  • m

p i l e d t

  • :

a ) J a v a s

  • u

r c e c

  • d

e b ) J a v a b y t e c

  • d

e 2 . D

  • e

s t h e f

  • l

l

  • w

i n g c

  • d

e c

  • m

p i l e ? I f n

  • t

, w h a t ’ s t h e e r r

  • r

? v a r s t r i n g = 1 s t r i n g = " a " 3 . D

  • e

s t h e f

  • l

l

  • w

i n g c

  • d

e c

  • m

p i l e ? I f n

  • t

, w h a t ’ s t h e e r r

  • r

? v a l l a n g u a g e s = l i s t O f ( " J a v a " ) l a n g u a g e s . a d d ( " K

  • t

l i n " ) 4 . W h a t w i l l b e p r i n t e d ? _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ p r i n t l n ( l i s t O f ( ' a ' , ' b ' , ' c ' ) . j

  • i

n T

  • S

t r i n g ( s e p a r a t

  • r

= " " , p r e f i x = " ( " , p

  • s

t f i x = " ) " ) ) 5 . W h a t w i l l b e p r i n t e d ( a

  • r

b ) ? f u n f

  • (

) : S t r i n g { p r i n t l n ( " C a l c u l a t i n g f

  • .

. . " ) r e t u r n " f

  • "

} f u n m a i n ( a r g s : A r r a y < S t r i n g > ) { p r i n t l n ( " F i r s t $ { f

  • (

) } , s e c

  • n

d $ { f

  • (

) } " ) } C a l c u l a t i n g f

  • .

. . F i r s t f

  • ,

s e c

  • n

d f

  • C

a l c u l a t i n g f

  • .

. . C a l c u l a t i n g f

  • .

. . F i r s t f

  • ,

s e c

  • n

d f

  • "

S c a l a " ) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ " S c a l a " ) ) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

___________________________________________ ____________________________

Workshop tomorrow

slide-108
SLIDE 108

Have a nice Kotlin!