It's 2017. Kotlin, a great language for the JVM, has been around for more than 6 years now and has changed the way a lot of developers look at the features and evolutionary progress of Java. Kotlin has become a very popular alternative to Java for Android developers and with Kotlin 1.1 being on its way, thing are going to become more exciting.
This talk will start with a brief introduction into Kotlin and its core language features. After this brief foray into concepts like Kotlin's immutable variables, null behaviour and other smarts like the syntactic sugar it provides for dealing with types and properties we'll have a look into what in store for Android developers and into new features in Kotlin 1.1, such as Kotlin Coroutines, Jack support for Android and lots of improvements to the standard library.
4. WHAT IS KOTLIN?
SOME KOTLIN FUNDAMENTALS
▸ Statically typed programming
language for JVM and Android
▸ Started as internal language “Project
Kotlin” at Jetbrains in July 2010
▸ Kotlin 1.0 since Feb 2016
▸ Now: Open-Source, Apache License
▸ Named after an island in the Gulf of
Finland
5. HISTORY OF KOTLIN (I)
▸ Jetbrains wanted a more efficient JVM language when building products
▸ Looked at Scala, Groovy, etc, but came up with their own language spec
▸ Shown first at the JVM Language Summit in 2011
▸ Got some traction in Android-land in 2014
▸ modern language features (lambdas, HOF etc) but Java 6-bytecode
▸ Low methods count (~7000)
▸ Strong focus on concision and an efficient, bloat-free language
WHAT IS KOTLIN?
6. HISTORY OF KOTLIN (II)
▸ Since 1.0 release: multiple maintenance releases up to 1.0.7
▸ 1.1 was released in Feb 2017, now at 1.1.1
▸ Kotlin/JS is a first-class deployment/compilation target now
▸ Coroutines
▸ Some stdlib cleanup
▸ Strong community, lots of interesting frameworks, awesome support from
Jetbrains
WHAT IS KOTLIN?
7. HOW DOES A SIMPLE CONVERSION LOOK LIKE?
public String listConvert(Collection<Integer> collection) {
StringBuilder sb = new StringBuilder();
sb.append("{");
Iterator<Integer> iterator = collection.iterator();
while (iterator.hasNext()) {
Integer element = iterator.next();
sb.append(element);
if (iterator.hasNext()) {
sb.append(", ");
}
}
sb.append("}");
return sb.toString();
}
fun listConvert(collection: Collection<Int>): String {
val sb = StringBuilder()
sb.append("{")
val iterator = collection.iterator()
while (iterator.hasNext()) {
val element = iterator.next()
sb.append(element)
if (iterator.hasNext()) {
sb.append(", ")
}
}
sb.append("}")
return sb.toString()
}
fun listConvertKt(collection: Collection<Int>): String {
return collection.joinToString(prefix = "{",postfix = "}")
}
WHAT IS KOTLIN?
9. IDIOMS & LANGUAGE PATTERNS
IDIOM AND LANGUAGE OVERVIEW
▸ Immutability
▸ String templates
▸ Null safety
▸ Properties and Fields
▸ Data classes
▸ Extension functions
▸ Syntactic sugar
▸ Type inference
▸ Lambdas
▸ Collection API
▸ Type-safe builders
▸ Java-Kotlin-Interop
10. IDIOMS & LANGUAGE PATTERNS
IMMUTABILITY
▸ Support for mutable and immutable
variables, properties and fields
▸ Keywords var and val
▸ val - immutable (recommended)
▸ var - mutable
▸ Similar concept applies for class
properties
val a: Int = 1
val b = 1
val c: Int
c = 1
val x = 23
// fails
x += 1
11. STRING TEMPLATES
▸ Kotlin Strings can contain template
expressions
▸ String templates start with a $ character
and
▸ can contain simple references such
as $s, as well as
▸ complex expressions in curly braces:
${s.length}
val s = "abc"
val str = "$s.length is ${s.length}"
Output:
abc.length is 3
IDIOMS & LANGUAGE PATTERNS
12. NULL SAFETY
▸ An explicit way to deal with NPEs
▸ Nullable types vs non-nullable types:
▸ String: no nullable
▸ String?: nullable
▸ Handle manually
▸ Use Safe Call operator ?.
▸ !! operator to allow/trigger a NPE
// Won't compile
var lastName: String = null
// Will compile
var lastNameNullable: String? = null
// Will also not compile
println(lastNameNullable.length)
// Option 1 (-1)
println(if (lastNameNullable != null)
lastNameNullable.length else -1)
// Option 2 (null)
println(lastNameNullable?.length)
// Option 3 (NPE)
println(lastNameNullable!!.length)
IDIOMS & LANGUAGE PATTERNS
13. PROPERTIES AND FIELDS
▸ Kotlin classes have mutable or
immutable properties
▸ Default getter/setters for properties,
can be customised
▸ An automated backing field can be
provided by the compiler (if required)
▸ Alternative: use an explicit backing
property
var counter = 0
set(value) {
if (value >= 0)
field = value
}
public class Address {
public var name: String = ...
public var street: String = ...
public var city: String = ...
public var state: String? = ...
public var zip: String = ...
}
IDIOMS & LANGUAGE PATTERNS
14. DATA CLASSES
▸ The POJOs/Beans of other languages
▸ Data classes implicitly create:
▸ getters/setters - recommend to use
val as often as possible.
▸ useful implementations for equals(),
hashCode(), toString(), copy()
▸ copy() has default parameters and
can be used to alter a copy
data class ChromeEncryptedPayload(
val encryptedPayload: String,
val encryptionHeader: String,
val cryptoKeyHeader: String)
val pl = ChromeEncryptedPayload(
encryptedPayload = "...",
encryptionHeader = "...",
cryptoKeyHeader = "...")
val anotherPl = pl.copy(
encryptedPayload = "...")
IDIOMS & LANGUAGE PATTERNS
15. SYNTACTIC SUGAR
▸ When-statement
▸ Ranges / Loops
▸ Destructuring
▸ Default and named arguments
IDIOMS & LANGUAGE PATTERNS
fun whatIs(x: Any) {
when (x) {
is Int -> println(x + 42)
is String -> println(x.length)
is IntArray -> println(x.sum())
}
}
whatIs(4) // 46
whatIs("4") // 1
whatIs(intArrayOf(1,2,3,4,5)) // 15
if (i in 1..10) {
println(i)
}
val (name, age) = person
fun read(b: Array<Byte>,
off: Int = 0,
len: Int = b.size()) {
…
}
16. EXTENSION FUNCTIONS
▸ Allow adding new functionality to a
class without inheritance or decorators
▸ Kotlin has extension functions as well
as extension properties
▸ Resolved statically, don’t actually
modify the class
fun Int.sum(otherInt: Int): Int = this +
otherInt
3.sum(7)
fun Activity.toast(message: CharSequence,
duration: Int =
TOAST.LENGTH_SHORT) {
Toast.makeText(this, message,
duration).show()
}
// In onCreate of an Activity
override fun onCreate(...) {
...
toast("Hi there")
...
}
IDIOMS & LANGUAGE PATTERNS
17. LAMBDAS
▸ Anonymous function or “function
literal”
▸ Closely related to the ideas of Higher-
Order-Functions
val sum = { x: Int, y: Int -> x + y }
val sum: (Int, Int) -> Int = { x, y ->
x + y }
private fun convertPetListToDomain(list: List<Pet>): List<PetDomain> {
return list.map { convertPetItemToDomain(it) }
}
private fun convertPetItemToDomain(pet: Pet): PetDomain {
return PetDomain(pet.age,pet.size,pet.id,pet.name,pet.sex,pet.breed)
}
IDIOMS & LANGUAGE PATTERNS
18. TYPE-SAFE BUILDERS (I)
▸ Builders are a very popular approach in
Groovy to define data in a declarative
way
▸ Often used for:
▸ generating XML or JSON
▸ UI layout (Swing components) etc
▸ In Kotlin, builders even can be type-
checked
JsonBuilder builder = new JsonBuilder()
builder.records {
car {
name 'HSV Maloo'
make 'Holden'
year 2006
country 'Australia'
}
}
String json = JsonOutput.prettyPrint
(builder.toString())
IDIOMS & LANGUAGE PATTERNS
19. TYPE-SAFE BUILDERS (II)
▸ html() is a function with a lambda as an
argument (init)
▸ init’s type is a function type with
receiver, this allows you to:
▸ pass receiver (of type HTML) to
function
▸ call members of instance inside the
function
fun result(args: Array<String>) =
html {
head {
title {”HTML in Kotlin"}
}
body {
...
}
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML()
html.init()
return html
}
IDIOMS & LANGUAGE PATTERNS
20. TYPE-SAFE BUILDERS (III)
▸ Html class has functions to build the
head and the body elements of the
DSL.
▸ Not shown: classes further down in the
hierachy:
▸ Head, Body etc.
▸ Complete HTML builder example at:
http://goo.gl/TndcC9
class Html {
...
fun head(headBuilder: Head.() -> Unit) {
head = Head()
head?.headBuilder()
}
fun body(bodyBuilder: Body.() -> Unit) {
body = Body()
body?.bodyBuilder()
}
}
IDIOMS & LANGUAGE PATTERNS
23. THE 1.1 RELEASE
OVERVIEW (I)
▸ JavaScript target is not experimental anymore (browser & NodeJS)
▸ Full Kotlin language support
▸ Large part of the stdlib is supported
▸ Coroutines (JVM, experimental)
▸ Lightweight concurrency mechanism
▸ Alternative to threads
▸ Tooling improvements
24. THE 1.1 RELEASE
OVERVIEW (II)
▸ Language features
▸ Type aliases
▸ Bound callable references
▸ More powerful data classes
▸ Destructuring in lambdas
▸ Property syntax
▸ Underscore-parameters for unused variables in lambdas
25. THE 1.1 RELEASE
COROUTINES (I)
▸ Asynchronous programming is becoming increasingly important
▸ Problem: need to avoid blocking introduces a lot of complexity
▸ Kotlin’s approach: Suspending functions
▸ Function/lambda that can be suspended and resumed
▸ Ideas similar to cooperative multi-tasking
▸ Minimal integration into the core language and stdlib, most of functionality
provided by libraries
26. THE 1.1 RELEASE
COROUTINES (II)
▸ Using coroutines requires explicit
import of the Kotlin coroutines libraries
▸ Suspending function can use other
suspending functions like delay()
▸ join() waits for the background job on
doWorld() to complete.
▸ Light-weight, can act like daemon
threads
fun main(args: Array<String>) =
runBlocking<Unit> {
val job = launch(CommonPool) { doWorld() }
println("Hello,")
job.join()
}
// this is a suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
27. THE 1.1 RELEASE
TOOLING
▸ General approach: avoid tooling to be bound to language releases
▸ But: there’s some new stuff in 1.1:
▸ Updates for all major IDE plugins
▸ Incremental compilation is now a first-class citizen
▸ Linting for Kotlin in Android Studio projects was improved
28. TYPE ALIASES
▸ Allow to define alternative
names for types
▸ Often used with generic types
▸ Different from import aliases
typealias OscarWinners = Map<String, String>
fun countLaLaLand(oscarWinners: OscarWinners) =
oscarWinners.count { it.value.contains("La La Land") }
fun checkLaLaLandIsTheBestMovie
(oscarWinners: Map<String, String>) =
oscarWinners["Best picture"] == "La La Land"
import domain.PetModel as domainPets
THE 1.1 RELEASE
29. CLASSES
▸ Kotlin 1.1 removes restrictions
around data classes and sealed
classes
▸ Sealed: don’t need subclassed
nested into them anymore
▸ Data: can now extend other
classes
THE 1.1 RELEASE
sealed class Expr {
class Const(val number: Double) : Expr()
class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
}
fun eval(expr: Expr): Double = when(expr) {
is Expr.Const -> expr.number
is Expr.Sum -> eval(expr.e1) + eval(expr.e2)
Expr.NotANumber -> Double.NaN
}
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
fun eval(expr: Expr): Double = when (expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
}
30. DESTRUCTURING LAMBDAS
▸ Easier unpacking arguments
passed to a lambda
THE 1.1 RELEASE
val map = mapOf(1 to "one", 2 to "two")
// before
println(map.mapValues { entry -> val (key, value) = entry
"$key -> $value!"
})
// now
println(map.mapValues { (key, value) -> "$key -> $value!" })
31. COMPATIBILITY
▸ Kotlin 1.1 is backwards compatible to 1.0 on the language and stdlib level
▸ Code that compiled and ran in 1.0 will compile and run in 1.1
▸ More on compat: http://kotlinlang.org/docs/reference/compatibility.html
THE 1.1 RELEASE
33. WHERE DOES THAT LEAVE ANDROID?
IT’S STILL JAVA 6
▸ All the new features still work on Java 6
▸ Can be used and deployed to pretty much any current Android device/version
34. WHERE DOES THAT LEAVE ANDROID?
COROUTINES
▸ At first glance they look like a JVM- or server-side-only feature
▸ However, there are at least 3 libraries around to make coroutines useful in
Android:
▸ Anko (support for coroutines since 0.10 beta)
▸ kotlinx-coroutines-android (support for UI operations)
▸ AsyncAwait
35. WHERE DOES THAT LEAVE ANDROID?
COROUTINES IN ANKO
▸ Add anko-coroutines dependency
▸ Earlier versions of Anko already had support for async handling
▸ New:
▸ Coroutines in listeners
▸ asReference()
▸ bg()
fun getData(): Data { ... }
fun showData(data: Data) { ... }
async(UI) {
val data: Deferred<Data> = bg {
// Runs on the background
getData()
}
// This code is executed on the UI thread
showData(data.await())
}
36. WHERE DOES THAT LEAVE ANDROID?
COROUTINES WITH KOTLINX-COROUTINES-ANDROID
▸ Centred around launch(UI) metaphor
▸ Launching coroutines in UI context:
▸ allows updating the UI from inside the coroutine and
▸ allows invoking suspending functions at the same time
▸ no frozen UI during delay()
▸ cancel() on coroutine in UI context allows stopping it
▸ Similar libraries exist for JavaFX and Swing
37. WHERE DOES THAT LEAVE ANDROID?
COROUTINES WITH KOTLINX-COROUTINES-ANDROID
fun setup(hello: TextView, fab: FloatingActionButton) {
val job = launch(UI) {
for (i in 10 downTo 1) {
hello.text = "Countdown $i ..."
delay(500)
}
hello.text = "Done!"
}
fab.setOnClickListener = { job.cancel() }
}
38. WHERE DOES THAT LEAVE ANDROID?
COROUTINES WITH ASYNCAWAIT
▸ Async/await approach
▸ Very rich library on top of Kotlin’s
coroutine core:
▸ awaitWithProgress
▸ try/catch/onError/finally
▸ Plugins for Retrofit and rxJava
async {
val result = await {
//Long running code
}
// Use result
}
async {
val repos = await { github.getRepos() }
showList(repos)
repos.forEach { repo ->
val stats = await { github.getStats
(repo.name) }
showStats(repo, stats)
}
}
39. class AnimalListAdapter constructor (val items: PetList,
val listener: ItemClickListener :
RecyclerView.Adapter<AnimalListAdapter.ViewHolder>() {
...
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: Item, listener: ItemClickListener {
itemView.setOnClickListener(listener)
}
}
}
typealias ItemClickListener = (View) -> (Unit)
WHERE DOES THAT LEAVE ANDROID?
TYPE ALIASES
▸ RecyclerView and adapter classes: Replace repeating types with a “click
listener” alias
class AnimalListAdapter constructor (val items: PetList,
val listener: (View) -> Unit) :
RecyclerView.Adapter<AnimalListAdapter.ViewHolder>() {
...
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: Item, listener: (View) -> Unit) {
itemView.setOnClickListener(listener)
}
}
}
40. WHERE DOES THAT LEAVE ANDROID?
TOOLING
▸ Since 1.1beta2: Support for the Jack toolchain (ironic, given that that’s all
gonna change again soon)
▸ Some new AS/IntelliJ intentions:
▸ Generating View constructors
▸ Merging if-statements and more
42. OUTSIDE THE BOX
WHAT ELSE CAN KOTLIN DO FOR YOU?
▸ Use it in Gradle instead of Groovy
▸ Use it as your main script language in TeamCity
▸ Use it with other JVM languages via JSR-223 (javax.script)
43. OUTSIDE THE BOX
KOTLIN/NATIVE
▸ Brand new preview: Kotlin/Native
▸ Idea: compiling to machine code
▸ Preview targets: OS X 10.10, Ubuntu, iOS, RaspPi
▸ Goal: Ubiquitous language allowing you to write anything from front end code
down to machine-code-level back end services
▸ More: https://blog.jetbrains.com/kotlin/2017/04/kotlinnative-tech-preview-
kotlin-without-a-vm/
44. OUTSIDE THE BOX
COMMUNITY
▸ Slack team with ~6000 people
▸ Jetbrains user group/community program
▸ Multiple books and online courses
▸ Jetbrains KEEP process is open for everyone
▸ 4-5x increase in Kotlin LOC in github over the last year
▸ Lots of interesting frameworks being developed
46. FINAL THOUGHTS
MATURITY AND FUTURE
▸ Kotlin 1.0 was a big step for the language, Kotlin 1.1 added very useful new
features
▸ Very mature for a 1.x release (but 6+ years in the making), full of great
concepts and idioms, getting better with every release
▸ Tool support is A+
▸ KEEP (Kotlin Evolution and Enhancement Process) helps to steer the
language’s future
48. FINAL THOUGHTS
GET IN TOUCH
Kai Koenig
Email/iMessage: kai@ventego-creative.co.nz
Work: http://www.ventego-creative.co.nz
Twitter: @AgentK
Telegram: @kaikoenig
Slideshare: /agentk