Slide 1

Slide 1 text

Svetlana Isakova You can do better with Kotlin

Slide 2

Slide 2 text

- modern - pragmatic - Android-friendly Kotlin Programming Language

Slide 3

Slide 3 text

Official on Android

Slide 4

Slide 4 text

Not only Android

Slide 5

Slide 5 text

Multiplatform projects

Slide 6

Slide 6 text

Pragmatic - tooling - Java interop

Slide 7

Slide 7 text

From

Slide 8

Slide 8 text

has good tooling

Slide 9

Slide 9 text

- completion - navigation - refactorings - inspections …

Slide 10

Slide 10 text

can be easily mixed with Java code

Slide 11

Slide 11 text

*.java *.class *.dex compiled to Java bytecode *.kt

Slide 12

Slide 12 text

Kotlin code Java code You can have Java & Kotlin code in one project

Slide 13

Slide 13 text

You can gradually add Kotlin to your existing app

Slide 14

Slide 14 text

Android-friendly

Slide 15

Slide 15 text

Android Studio is based on IntelliJ IDEA

Slide 16

Slide 16 text

just another library for your app rxjava-2.1.2 kotlin-stdlib-1.1.4 6315 10212

Slide 17

Slide 17 text

No Kotlin SDK …just JDK + extensions small runtime jar easy Java interop

Slide 18

Slide 18 text

Modern - concise - safe - expressive

Slide 19

Slide 19 text

concise

Slide 20

Slide 20 text

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 21

Slide 21 text

- equals - hashCode - toString 
 data 
 class Person(val name: String, val age: Int)

Slide 22

Slide 22 text

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 23

Slide 23 text


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

Slide 24

Slide 24 text

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 25

Slide 25 text

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 26

Slide 26 text

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 27

Slide 27 text

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 28

Slide 28 text

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 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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 32

Slide 32 text

safe

Slide 33

Slide 33 text

Billion Dollar Mistake

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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 36

Slide 36 text

val s: String? if (s != null) {
 s.length
 } Dealing with Nullable Types

Slide 37

Slide 37 text

s?.length val s: String? Dealing with Nullable Types

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

val s: String? if (s == null) fail()
 s.length Control-flow analysis

Slide 42

Slide 42 text

val s: String? Making NPE explicit s!! throws NPE if s is null s!!.length

Slide 43

Slide 43 text

Nullable Types Under the Hood No performance overhead @Nullable, @NotNull annotations

Slide 44

Slide 44 text

Annotate your Java types in Kotlin Type behaves like regular Java type @Nullable @NotNull Type Type? Type Type @ParametersAreNonnullByDefault @MyNonnullApi Type/Type?

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

expressive

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Extension Functions

Slide 49

Slide 49 text

fun String.lastChar() = get(length - 1) this can be omitted Extension Functions fun String.lastChar() = this.get(this.length - 1)

Slide 50

Slide 50 text

import com.example.util.lastChar import com.example.util.* Extension Functions val c: Char = "abc".lastChar() fun String.lastChar() = get(length - 1)

Slide 51

Slide 51 text

fun String.lastChar() = get(length - 1) Calling Extension Functions from Java code StringExtensions.kt char c = StringExtensionsKt.lastChar("abc"); JavaClass.java import static StringExtensionsKt.lastChar; char c = lastChar("abc");

Slide 52

Slide 52 text

No. Because it’s a regular static method under the hood. fun String.lastChar() = get(length - 1) Extension Functions Is it possible to call a private member of String here?

Slide 53

Slide 53 text

Extensions for Android Toast.makeText(this, "Thank you!”, Toast.LENGTH_SHORT).show() Activity extension function on Activity toast("Thank you!") this.toast("Thank you!")

Slide 54

Slide 54 text

this.startActivity(“ANSWER" to 42) val intent = Intent(this, NewActivity::class.java)
 intent.putExtra("ANSWER", 42)
 startActivity(intent) Extensions for Android

Slide 55

Slide 55 text

infix fun A.to(that: B) = Pair(this, that) "ANSWER".to(42) "hot" to RED mapOf(0 to "zero", 1 to "one") The to extension function

Slide 56

Slide 56 text

Lambdas

Slide 57

Slide 57 text

Lambdas button.addActionListener { println("Hi") }

Slide 58

Slide 58 text

{ employee: Employee -> employee.city == City.PRAGUE } What’s an average age of employees working in Prague? Working with collections with Lambdas val employees: List employees.filter { it.city == City.PRAGUE }.map { it.age }.average() data class Employee( val city: City, val age: Int )

Slide 59

Slide 59 text

What’s an average age of employees working in Prague? Working with collections with Lambdas val employees: List data class Employee( val city: City, val age: Int ) extension functions employees.filter { it.city == City.PRAGUE }.map { it.age }.average()

Slide 60

Slide 60 text

Kotlin library: extensions on collections • filter • map • reduce • count • find • any • flatMap • groupBy • …

Slide 61

Slide 61 text

Under the Hood No performance overhead Lambdas can be inlined

Slide 62

Slide 62 text

Extension Function & Lambda Lambda with receiver

Slide 63

Slide 63 text

val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 append(c)
 } toString()
 } The with function with is a function val sb = StringBuilder()
 sb.appendln("Alphabet: ")
 for (c in 'a'..'z') {
 sb.append(c)
 }
 sb.toString()


Slide 64

Slide 64 text

lambda is its second argument val sb = StringBuilder()
 with (sb) {
 this.appendln(“Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 } this.toString()
 } val sb = StringBuilder()
 with (sb, { ->
 this.appendln(“Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 } this.toString()
 }) lambda is its second argument Lambda with receiver with is a function this is an implicit receiver in the lambda val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 append(c)
 } toString()
 } this can be omitted

Slide 65

Slide 65 text

with (sb) {
 appendln("Alphabet: ")
 ...
 } inline fun with( receiver: T, block: T.() -> R ): R = receiver.block() The with function declaration

Slide 66

Slide 66 text

Lambda with receiver val sb = StringBuilder()
 with (sb) {
 appendln("Alphabet: ")
 for (c in 'a'..'z') {
 this.append(c)
 }
 } lambda with implicit this

Slide 67

Slide 67 text

html {
 table {
 for (product in products) {
 tr {
 td { text(product.description) }
 td { text(product.price) }
 td { text(product.popularity) }
 }
 }
 }
 } HTML Builders lambdas with receiver

Slide 68

Slide 68 text

val db: SQLiteDatabase = … db.beginTransaction()
 try {
 db.delete("users", "first_name = ?", arrayOf("Jake"))
 db.setTransactionSuccessful()
 } finally {
 db.endTransaction()
 } db.inTransaction {
 delete("users", "first_name = ?", arrayOf("Jake"))
 } Avoiding Duplication

Slide 69

Slide 69 text

db.beginTransaction()
 try {
 db.delete("users", "first_name = ?", arrayOf("Jake"))
 db.setTransactionSuccessful()
 } finally {
 db.endTransaction()
 } db.inTransaction {
 delete("users", "first_name = ?", arrayOf("Jake"))
 } Inline functions is declared as inline function generated bytecode is similar to

Slide 70

Slide 70 text

ANKO-DSL DSL for dynamic layouts

Slide 71

Slide 71 text

Alerts fun Activity.showAreYouSureAlert(process: () -> Unit) {
 alert(title = "Are you sure?",
 message = "Are you really sure?") {
 positiveButton("Yes") { process() }
 negativeButton("No") { }
 }.show()
 } Are you sure? Are you really sure? No Yes

Slide 72

Slide 72 text

customView {
 verticalLayout {
 val email = editText {
 hint = "Email"
 }
 
 val password = editText {
 hint = "Password"
 transformationMethod = PasswordTransformationMethod.getInstance()
 }
 
 positiveButton("Log In") {
 logIn(email.text, password.text)
 }
 }
 } Password Log In Email Custom layouts

Slide 73

Slide 73 text

kotlinlang.org

Slide 74

Slide 74 text

Gradle & Kotlin Writing Gradle build scripts and plugins in Kotlin

Slide 75

Slide 75 text

try.kotlinlang.org

Slide 76

Slide 76 text

Kotlin Koans

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

Have a nice Kotlin!