Statically typed programming language
for the JVM, Android and the browser
100% interoperable with Java™
Slide 3
Slide 3 text
Kotlin Java 6
Slide 4
Slide 4 text
Android
bytecode
Java
code
Kotlin
code
javac kotlinc
Dalvik Art
Slide 5
Slide 5 text
How to add Kotlin to your project?
1. Add Kotlin Plugin
Slide 6
Slide 6 text
How to add Kotlin to your project?
2. Declare dependencies
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin-android'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Slide 7
Slide 7 text
How to add Kotlin to your project?
2. Declare dependencies
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin-android'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
Slide 8
Slide 8 text
What does it look like?
val a: Int = 1
Read only variable
Slide 9
Slide 9 text
What does it look like?
val a: Int = 1
val b = 1
Int type is inferred
Slide 10
Slide 10 text
What does it look like?
val a: Int = 1
val b = 1
var c: Int
Mutable variable
Slide 11
Slide 11 text
What does it look like?
val a: Int = 1
val b = 1
var c: Int
c = 2
Slide 12
Slide 12 text
What does it look like?
val a: Int = 1
val b = 1
var c: Int
c = 2
val date = Date()
print(date.time)
Instances of class
Slide 13
Slide 13 text
What does it look like?
class Main {
fun printSum(a: Int, b: Int) {
print(a + b)
}
fun returnSum(a: Int, b: Int): Int {
return a + b
}
}
Class name
Slide 14
Slide 14 text
What does it look like?
class Main {
fun printSum(a: Int, b: Int) {
print(a + b)
}
fun returnSum(a: Int, b: Int): Int {
return a + b
}
}
Slide 15
Slide 15 text
What does it look like?
class Main {
fun printSum(a: Int, b: Int) {
print(a + b)
}
fun returnSum(a: Int, b: Int): Int {
return a + b
}
}
Function name
Slide 16
Slide 16 text
What does it look like?
class Main {
fun printSum(a: Int, b: Int) {
print(a + b)
}
fun returnSum(a: Int, b: Int): Int {
return a + b
}
}
Function arguments
Slide 17
Slide 17 text
What does it look like?
class Main {
fun printSum(a: Int, b: Int) {
print(a + b)
}
fun returnSum(a: Int, b: Int): Int {
return a + b
}
}
Return type
Slide 18
Slide 18 text
Kotlin Features
String templates
Properties
Lambdas
Data class
Smart cast
Null safety
Default values for function parameters
Lazy property
Extension Functions
Single-expression functions
When expression
let, apply, use, with
Collections
Kotlin Android Extensions Plugin
Anko
Slide 19
Slide 19 text
String templates
val query = "Kotlin"
val language = "en"
val url = "https://www.google.com.ua/#q=$query&language=$language"
Slide 20
Slide 20 text
String templates
val query = "Kotlin"
val language = "en"
val url = "https://www.google.com.ua/#q=$query&language=$language"
Slide 21
Slide 21 text
String templates
val query = "Kotlin"
val language = "en"
val url = "https://www.google.com.ua/#q=$query&language=$language"
> https://www.google.com.ua/#q=Kotlin&language=en
Slide 22
Slide 22 text
Properties
class User {
var name: String? = null
var age: Int? = null
}
Slide 23
Slide 23 text
Properties
class User {
var name: String? = null
var age: Int? = null
}
val user = User()
user.name = "John"
user.age = 24
print("User name:${user.name}")
Slide 24
Slide 24 text
Properties
class User {
var name: String? = null
var age: Int? = null
set(value) {
if (value >= 0)
field = value
}
}
Slide 25
Slide 25 text
Lambdas
Function that is not declared, but passed immediately as an expression.
Data class
● getters, setters
● equals()/hashCode()
● toString() of the form "User(name=John, age=42)"
● copy() function
Nothing, just hold data
What it does?
What it provides?
Slide 36
Slide 36 text
Data class
data class User(val name: String, val age: Int)
Slide 37
Slide 37 text
Data class
data class User(val name: String, val age: Int)
val user = User("Dmytro", 24)
print(user)
> User(name=Dmytro, age=24)
Slide 38
Slide 38 text
Smart cast
fun demo(x: Any) {
if (x is String) {
print(x.length)
} else if (x is Int) {
print(x * x)
}
}
Slide 39
Slide 39 text
Smart cast
fun demo(x: Any) {
if (x is String) {
print(x.length)
} else if (x is Int) {
print(x * x)
}
}
x is automatically cast to String
Slide 40
Slide 40 text
Smart cast
fun demo(x: Any) {
if (x is String) {
print(x.length)
} else if (x is Int) {
print(x * x)
}
}
x is automatically cast to Int
Slide 41
Slide 41 text
Smart cast
fun demo(x: Any) {
if (x is String) {
print(x.length)
} else if (x is Int) {
print(x * x)
}
}
Slide 42
Slide 42 text
Null safety
Kotlin’s type system is aimed to eliminate NullPointerException’s from our code.
Slide 43
Slide 43 text
Null safety
var name: String = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState.getString("name")
}
Slide 44
Slide 44 text
Null safety
var name: String = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState.getString("name")
}
Compilation error, non null variable
Slide 45
Slide 45 text
Null safety
var name: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState.getString("name")
}
Slide 46
Slide 46 text
Null safety
var name: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState.getString("name")
}
Compilation error, argument may be null
Slide 47
Slide 47 text
Null safety
var name: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState?.getString("name")
}
Slide 48
Slide 48 text
Null safety
var name: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
name = savedInstanceState?.getString("name")
}
Slide 49
Slide 49 text
Default values for function parameters
Function parameters can have default values, which are used when a corresponding
argument is omitted.
This allows for a reduced number of overloads compared to other languages.
Slide 50
Slide 50 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String?,
selectionArgs : Array?,
orderBy: String?): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), null, null, "NAME")
Slide 51
Slide 51 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String? = null,
selectionArgs : Array? = null,
orderBy: String? = null): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), null, null, "NAME")
Default value
Slide 52
Slide 52 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String? = null,
selectionArgs : Array? = null,
orderBy: String? = null): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), null, null, "NAME")
Slide 53
Slide 53 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String? = null,
selectionArgs : Array? = null,
orderBy: String? = null): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), null, null, orderBy = "NAME")
Named argument
Slide 54
Slide 54 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String? = null,
selectionArgs : Array? = null,
orderBy: String? = null): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), null, null, orderBy = "NAME")
Not need
Slide 55
Slide 55 text
Default values for function parameters
fun query(table: String,
columns: Array,
selection: String? = null,
selectionArgs : Array? = null,
orderBy: String? = null): Cursor {
...
}
// function call
query("USERS", arrayOf("ID", "NAME"), orderBy = "NAME")
Slide 56
Slide 56 text
Lazy property
Value gets computed only upon first access.
Slide 57
Slide 57 text
Lazy property
val preference = getSharedPreferences("pref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val username = preference.getString("username")
}
Slide 58
Slide 58 text
Lazy property
val preference = getSharedPreferences("pref")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val username = preference.getString("username")
}
Crash, require context
Slide 59
Slide 59 text
Lazy property
val preference by lazy { getSharedPreferences("pref") }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val username = preference.getString("username")
}
Won’t be executed until the
property is first used
Slide 60
Slide 60 text
Lazy property
val preference by lazy { getSharedPreferences("pref") }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val username = preference.getString("username")
}
Slide 61
Slide 61 text
Extension Functions
Extensions do not actually modify classes they extend. By defining an
extension, you do not insert new members into a class, but merely make
new functions callable with the dot-notation on instances of this class.
Provides the ability to extend a class with new functionality without having
to inherit from the class.
What it does?
How?
Extension Functions
fun ImageView.loadUrl(url: String) {
Picasso.with(context).load(url).into(this)
}
ViewExtensions.kt
imageView.loadUrl("http://....")
MainActivity.kt
Type being extended
Single-expression functions
When a function returns a single expression, the curly braces can be
omitted and the body is specified after a = symbol.
Slide 67
Slide 67 text
Single-expression functions
fun createUrl(search: String): String {
return "www.google.com.ua/#q=$search"
}
Slide 68
Slide 68 text
Single-expression functions
fun createUrl(search: String): String {
return "www.google.com.ua/#q=$search"
}
Function returns a single expression
Slide 69
Slide 69 text
Single-expression functions
fun createUrl(search: String): String = "www.google.com.ua/#q=$search"
Curly braces can be omitted
body is specified after a = symbol
Slide 70
Slide 70 text
Single-expression functions
fun createUrl(search: String): String = "www.google.com.ua/#q=$search"
Return type is optional
Slide 71
Slide 71 text
Single-expression functions
fun createUrl(search: String) = "www.google.com.ua/#q=$search"
Slide 72
Slide 72 text
When expression
When expression is similar to switch/case in Java, but far more powerful.
Slide 73
Slide 73 text
When expression
when (argument) {
match1 -> fun1()
match2 -> fun2()
else -> fun3()
}
Slide 74
Slide 74 text
When expression
when (argument) {
match1 -> fun1()
match2 -> fun2()
else -> fun3()
}
Can be anything
Slide 75
Slide 75 text
When expression
when (argument) {
match1 -> fun1()
match2 -> fun2()
else -> fun3()
}
Can be anything
Slide 76
Slide 76 text
When expression
var result: Int = when (argument) {
match1 -> fun1()
match2 -> fun2()
else -> fun3()
}
Can return result
Slide 77
Slide 77 text
When expression
var result: Int = when (argument) {
match1 -> fun1()
match2 -> fun2()
else -> fun3()
}
Slide 78
Slide 78 text
When expression
override fun onCreateViewHolder(g: ViewGroup, type: Int) {
when (type) {
TYPE_TITLE -> TitleViewHolder(g)
TYPE_DESCRIPTION -> DescriptionViewHolder(g))
}
return null
}
Slide 79
Slide 79 text
When expression
override fun onCreateViewHolder(g: ViewGroup, type: Int) {
when (type) {
TYPE_TITLE -> TitleViewHolder(g)
TYPE_DESCRIPTION -> DescriptionViewHolder(g))
}
return null
}
Can be placed after a = symbol
Slide 80
Slide 80 text
When expression
override fun onCreateViewHolder(g: ViewGroup, type: Int) = when (type) {
TYPE_TITLE -> TitleViewHolder(g)
TYPE_DESCRIPTION -> DescriptionViewHolder(g))
else -> null
}
Slide 81
Slide 81 text
When expression
override fun onCreateViewHolder(g: ViewGroup, type: Int) = when (type) {
TYPE_TITLE -> TitleViewHolder(g)
TYPE_DESCRIPTION -> DescriptionViewHolder(g)
else -> null
}
Slide 82
Slide 82 text
When expression
override fun getItemViewType(index: Int) = when (dataList[index]) {
is Title -> TYPE_TITLE
is Description -> TYPE_DESCRIPTION
else -> TYPE_UNDEFINED
}
Slide 83
Slide 83 text
When expression
override fun getItemViewType(index: Int) = when (dataList[index]) {
is Title -> TYPE_TITLE
is Description -> TYPE_DESCRIPTION
else -> TYPE_UNDEFINED
}
Type checks possible
Slide 84
Slide 84 text
When expression
override fun getItemViewType(index: Int) = when (dataList[index]) {
is Title -> TYPE_TITLE
is Description -> TYPE_DESCRIPTION
else -> TYPE_UNDEFINED
}
Slide 85
Slide 85 text
When expression
override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) {
val displayable: Displayable = dataList[index]
when (displayable) {
is Title -> initTitle(viewHolder, displayable)
is Description -> initDescription(viewHolder, displayable)
}
}
Slide 86
Slide 86 text
When expression
override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) {
val displayable: Displayable = dataList[index]
when (displayable) {
is Title -> initTitle(viewHolder, displayable)
is Description -> initDescription(viewHolder, displayable)
}
}
Smart cast
Slide 87
Slide 87 text
When expression
override fun onBindViewHolder(viewHolder: ViewHolder, index: Int) {
val displayable: Displayable = dataList[index]
when (displayable) {
is Title -> initTitle(viewHolder, displayable)
is Description -> initDescription(viewHolder, displayable)
}
}
Slide 88
Slide 88 text
let, apply, use, with
Higher-order functions - function that takes functions as parameters, or
returns a function.
Slide 89
Slide 89 text
let (scope function)
/**
* Calls the specified function [block] with `this` value as
* its argument and returns its result.
*/
public inline fun T.let(block: (T) -> R): R = block(this)
Slide 90
Slide 90 text
let
Preferences.getUser().let {
showUserName(it.name)
showUserEmail(it.email)
}
Slide 91
Slide 91 text
let
Preferences.getUser().let {
showUserName(it.name)
showUserEmail(it.email)
}
Refers to user object
Slide 92
Slide 92 text
let
Preferences.getUser().let {
showUserName(it.name)
showUserEmail(it.email)
}
Variable visibility scope
Slide 93
Slide 93 text
let
Preferences.getUser()?.let {
showUserName(it.name)
showUserEmail(it.email)
}
Only execute if user is not null
Slide 94
Slide 94 text
let
Preferences.getUser()?.let {
showUserName(it.name)
showUserEmail(it.email)
}
Slide 95
Slide 95 text
use (try with resources function)
/**
* Executes the given [block] function on this resource and then
* closes it down correctly whether an exception is thrown or not.
*/
public inline fun T.use(block: (T) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Exception) {
// ommitted
} finally {
if (!closed) {
close()
}
}
}
Slide 96
Slide 96 text
use
fun countUsers(): Long {
val database = openDatabase()
val result = database.count("users")
database.close()
return result
}
Slide 97
Slide 97 text
use
fun countUsers() = openDatabase().use { it.count("users") }
Automatically close database
Slide 98
Slide 98 text
use
fun countUsers() = openDatabase().use { it.count("users") }
Refers to database object
Slide 99
Slide 99 text
use
fun countUsers() = openDatabase().use { it.count("users") }
Slide 100
Slide 100 text
with
/**
* Calls the specified function [block] with the given [receiver]
* as its receiver and returns its result.
*/
public inline fun with(receiver: T, block: T.() -> R): R = receiver.block()
Slide 101
Slide 101 text
with
recyclerView.setHasFixedSize(true)
recyclerView.addItemDecoration(createDecorator())
recyclerView.layoutManager = LinearLayoutManager(applicationContext)
recyclerView.adapter = myAdapter
with
with(recyclerView) {
recyclerView.setHasFixedSize(true)
recyclerView.addItemDecoration(createDecorator())
recyclerView.layoutManager = LinearLayoutManager(applicationContext)
recyclerView.adapter = myAdapter
}
Not need
apply
/**
* Calls the specified function [block] with `this` value as its receiver
* and returns `this` value.
*/
public inline fun T.apply(block: T.() -> Unit): T { block(); return this }
Slide 107
Slide 107 text
apply
fun makeDir(path: String): File {
val result: File = File(path)
result.mkdirs()
return result
}
Slide 108
Slide 108 text
apply
fun makeDir(path: String) = File(path).apply { mkdirs() }
Slide 109
Slide 109 text
Collections
val numbers: MutableList = mutableListOf(1, 2, 3)
numbers.add(1)
val numbers2: List = listOf(1, 2, 3)
numbers2.add(1)
No such method
Kotlin Android Extensions Plugin
Adds a hidden caching function and a field inside each Kotlin Activity.
Provides reference to all layout views (which have id’s) with single line of
code.
What it does?
How?
Kotlin Android Extensions Plugin
// R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*
public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtTitle.setText("Hello, Kotlin!")
btnHello.setOnClickListener {...}
}
}
Slide 118
Slide 118 text
Kotlin Android Extensions Plugin
// R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*
public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtTitle.setText("Hello, Kotlin!")
btnHello.setOnClickListener {...}
}
}
Slide 119
Slide 119 text
Kotlin Android Extensions Plugin
// R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*
public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtTitle.setText("Hello, Kotlin!")
btnHello.setOnClickListener {...}
}
}
Instead of findView(R.id.txtTitle)
Slide 120
Slide 120 text
Kotlin Android Extensions Plugin
// R.layout.activity_main
import kotlinx.android.synthetic.main.activity_main.*
public class MyActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
txtTitle.setText("Hello, Kotlin!")
btnHello.setOnClickListener {...}
}
}
Slide 121
Slide 121 text
Anko
Kotlin library from JetBrains which provide API to make Android
application development faster and easier.
What it does?
Slide 122
Slide 122 text
Anko
dependencies {
compile "org.jetbrains.anko:anko-common:$anko_version"
compile "org.jetbrains.anko:anko-sqlite:$anko_version"
}
Slide 123
Slide 123 text
Anko
toast("Hi there!")
toast(R.string.message)
longToast("Wow, such a duration")
Slide 124
Slide 124 text
Anko
alert("Santa", "You were a good boy?") {
positiveButton("Yes") { toast("You are now in GOOD list") }
negativeButton("No") { toast("You are now in BAD list") }
}.show()
val countries = listOf("Ukraine", "USA", "UK",)
selector("Where are you from?", countries) { i ->
toast("So you're living in ${countries[i]}, right?")
}
Slide 125
Slide 125 text
Anko
async() {
// long background task
uiThread {
// won't be executed if isFinishing() is true
toolbar.title = "Done"
}
}
Slide 126
Slide 126 text
Anko
database.use {
createTable("Customer", ifNotExists = true,
"_id" to INTEGER + PRIMARY_KEY + UNIQUE,
"name" to TEXT,
"photo" to BLOB)
}
Slide 127
Slide 127 text
Resources
www.kotlinlang.org/docs/reference
www.try.kotlinlang.org
www.antonioleiva.com/kotlin
- documentation
- online compiler + exercises
- kotlin blog (by Antonio Leiva)
Slide 128
Slide 128 text
@dmytrodanylyk
slides.com/dmytrodanylyk
www.dmytrodanylyk.com
S
speakerdeck.com/dmytrodanylyk
S