KAI KOENIG (@AGENTK)
LITTLE HELPERS FOR ANDROID
DEVELOPMENT WITH KOTLIN
AGENDA
What is Kotlin?
Common idioms and language concepts
Kotlin and Android
Anko
Other libraries and tools for Kotlin and Android
Final thoughts
WHAT IS KOTLIN?
WHAT IS KOTLIN?
SOME FUNDAMENTALS
Statically typed programming language for the
JVM and Android as well as the browser
Started as internal language Project Kotlin at
Jetbrains in 2010
Now: Open-Source, Apache License - Kotlin 1.0
released in Feb 2016
Kotlin SDK plus tool support for IntelliJ,
Android Studio, Eclipse
Named after an island in the Gulf of Finland
WHAT IS KOTLIN?
MOTIVATION FOR KOTLIN
The Java platform is awesome, but it has its issues:
Sometimes tied to backwards/legacy compatibility
Can be a very verbose language and produce bloated code
Type system has various flaws
Kotlin aims to fix a lot of those issues, in particular when one has to use Java 6
or 7 (if were lucky) and cant use all the new, shiny features from Java 8 and
soon Java 9 and 10.
WHAT IS KOTLIN?
HOW DOES A SIMPLE CONVERSION LOOK LIKE?
public String listConvert(Collection<Integer> collection) { fun listConvert(collection: Collection<Int>): String {
StringBuilder sb = new StringBuilder(); val sb = StringBuilder()
sb.append("{"); sb.append("{")
Iterator<Integer> iterator = collection.iterator(); val iterator = collection.iterator()
while (iterator.hasNext()) { while (iterator.hasNext()) {
Integer element = iterator.next(); val element = iterator.next()
sb.append(element); sb.append(element)
if (iterator.hasNext()) { if (iterator.hasNext()) {
sb.append(", "); sb.append(", ")
} }
} }
sb.append("}"); sb.append("}")
return sb.toString(); return sb.toString()
} }
fun listConvertKt(collection: Collection<Int>): String {
return collection.joinToString(prefix = "{",postfix = "}")
}
COMMON IDIOMS &
LANGUAGE PATTERNS
https://www.flickr.com/photos/geraldford/6976818221/
COMMON IDIOMS AND LANGUAGE CONCEPTS
OVERVIEW
Immutability Syntactic sugar (loops, ranges etc)
String templates & Enum classes Extension functions
Null safety Lambdas
Properties and Fields Collection API
Type inference and casts Type-safe builders
Data classes Java-Kotlin-Interop
COMMON IDIOMS AND LANGUAGE CONCEPTS
IMMUTABILITY
Built-in support for mutable and immutable val a: Int = 1
variables, properties and fields val b = 1
Keywords var and val val c: Int
c = 1
val - immutable (recommended)
var x = 23
var - mutable x += 1
Similar concept applies for class properties, val
creates getters, var creates getters and setters
(more later)
COMMON IDIOMS AND LANGUAGE CONCEPTS
STRING TEMPLATES & ENUM CLASSES
val s = "abc"
Kotlin Strings can contain template expressions val str = "$s.length is ${s.length}"
enum class Locale(val hello: String) {
Start with a $ character and DE_DE("Hallo"), EN_NZ("Hello"), MI_NZ("Kia Ora")
}
can contain simple references: class Customer(val firstName:String,
val lastName:String,
$s val locale: Locale = Locale.DE_DE) {
fun sayHello() = println("${locale.hello},
$firstName $lastName")
complex expressions in curly braces: }
${s.length} fun main(args : Array<String>) {
val myCustomer = Customer("Sandra",
"Musterfrau",
Kotlin has a dedicated enum class, very similar Locale.MI_NZ)
myCustomer.sayHello()
to Java }
COMMON IDIOMS AND LANGUAGE CONCEPTS
NULL SAFETY
// Won't compile
Motivation: A better way to deal with NPEs var lastName: String = null
Kotlin differentiates nullable types from non- // Will compile
var lastNameNullable: String? = null
nullable types by adding a ? to the type:
// Will also not compile
println(lastNameNullable.length)
String: no nullable
// Option 1 (-1)
println(if (lastNameNullable != null)
String?: nullable lastNameNullable.length else -1)
// Option 2 (null)
Handle manually or use Safe Call operator ?. or println(lastNameNullable?.length)
use the !! operator to allow/trigger a NPE.
// Option 3 (NPE)
println(lastNameNullable!!.length)
COMMON IDIOMS AND LANGUAGE CONCEPTS
PROPERTIES AND FIELDS
var counter = 0
Kotlin classes have mutable or immutable set(value) {
properties if (value >= 0)
field = value
}
An automated backing field can be provided
by the compiler (if deemed necessary) public class MyTest {
lateinit var subject: TestSubject
Default getter/setters for properties, can be @SetUp fun setup() {
customised subject = TestSubject()
}
lateinit modifier to deal with non-nullable @Test fun test() {
properties that cant be initialised in the subject.method()
constructor }
}
COMMON IDIOMS AND LANGUAGE CONCEPTS
TYPE INFERENCE AND CASTS (I)
When possible, Kotlin will infer the type of val b: Byte = 1
variables // This won't work
val i: Int = b
Explicit conversions, type widening and // This will
inference val i: Int = b.toInt()
Smaller types are not subtypes of bigger
val l = 1L + 3
types, no implicit conversion
Types are often inferred from the context
COMMON IDIOMS AND LANGUAGE CONCEPTS
TYPE INFERENCE AND CASTS (II)
is or !is checks if an object adheres to a certain fun whatIs(x: Any) {
when (x) {
type is Int -> println(x + 42)
is String -> println(x.length)
Smart cast: Compiler tracks is-expressions for is IntArray -> println(x.sum())
immutable values }
}
works for val local variables and private, whatIs(4) // 46
internal or in module performed casts whatIs("4") // 1
whatIs(intArrayOf(1,2,3,4,5)) // 15
works for var local variables if the variable
hasnt been modified between check and
usage, never for var properties
COMMON IDIOMS AND LANGUAGE CONCEPTS
DATA CLASSES
The POJOs or Beans of other languages data class ChromeEncryptedPayload(
val encryptedPayload: String,
val encryptionHeader: String,
Data classes implicitly create: val cryptoKeyHeader: String)
getters/setters (the latter if a property is var)
equals(), hashCode(), toString(), copy() - can
be overwritten by custom implementations
copy() has default parameters and can be
used to alter a copy
parameterless constructors need default
parameters specified
COMMON IDIOMS AND LANGUAGE CONCEPTS
EXTENSION FUNCTIONS
fun Int.sum(otherInt: Int): Int = this +
Allow adding new functionality to a class otherInt
without inheritance or Decorators
3.sum(7)
Kotlin allows extension functions and extension
fun Activity.toast(message: CharSequence,
properties duration: Int =
TOAST.LENGTH_SHORT) {
Toast.makeText(this, message,
Resolved statically, do not actually modify duration).show()
the class (excellent example why this has to }
be the case on https://kotlinlang.org/docs/ // In onCreate of an Activity
override fun onCreate(...) {
reference/extensions.html) ...
toast("Hi there")
...
}
COMMON IDIOMS AND LANGUAGE CONCEPTS
JAVA-KOTLIN-INTEROP
Java and Kotlin are fully interoperable from an integration point of view
Your Java code can call and use Kotlin code
Your Kotlin code can call and use Java code
The latter is in particular useful because it means you can continue to use pretty
much any existing Android/Java library
Check out Hendrik Kokocinskis sample Kotlin app that uses all kinds of well
known Android/Java libs: https://github.com/blob0815/kotlin-android-sample
COMMON IDIOMS AND LANGUAGE CONCEPTS
OVERVIEW
Immutability Syntactic sugar (loops, ranges etc)
String templates & Enum classes Extension functions
Null safety Lambdas
Properties and Fields Collection API
Type inference and casts Type-safe builders
Data classes Java-Kotlin-Interop
KOTLIN & ANDROID
https://realm.io/assets/img/news/tutorial-kotlin-anko-cover.png
KOTLIN AND ANDROID
TOOLCHAIN AND FLOW
Kotlin sources Java sources
i n c jav
t l ac
ko
Bytecode
Dalvik ART JVM
KOTLIN AND ANDROID
PROJECT SETUP
Use Android Studio 1.5.x/2.x or IntelliJ 15/2016
Install Kotlin plugin (comes with Jetbrains plugins nowadays)
Gradle dependencies project-level:
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.2"
Gradle dependencies module-level:
compile 'org.jetbrains.kotlin:kotlin-stdlib:1.0.2'
apply plugin: 'kotlin-android'
main.java.srcDirs += 'src/main/kotlin'
KOTLIN AND ANDROID
KOTLIN EXTENSIONS FOR ANDROID (I)
Provides of a set of synthetic properties that bind views to those properties
Alternative to Butter Knife-style bindings, no need for additional runtime
library (Kotlin Extensions for Android are a Kotlin compiler plugin)
import kotlinx.android.synthetic.main.<layout>.*
import kotlinx.android.synthetic.main.<layout>.view.*
usage: <componentid>.doSomething()
Integrates nicely with build flavors, too
KOTLIN AND ANDROID
SYNTHETIC PROPERTIES
package ventegocreative.co.nz.kotlindemo
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
helloworld.text = "Hey, I'm dynamically set"
}
}
KOTLIN AND ANDROID
KOTLIN EXTENSIONS FOR ANDROID (II)
Used to be part of a separate plugin (https://plugins.jetbrains.com/plugin?
pluginId=7717)
obsolete since December 2015
functionality rolled into the main Kotlin plugin
still needs a very particular setup (not properly documented but in this place:
https://youtrack.jetbrains.com/issue/KT-10336)
TLDR: move dependencies in app module(s), not top-level Gradle file.
KOTLIN AND ANDROID
KOTLIN EXTENSIONS FOR ANDROID (III)
The current assumption is that Jetbrains plan to add more to the Kotlin
Extensions for Android, but we dont really know for sure at this stage.
Current feature of view binding:
Fresh take on view binding
Very simple to setup and use
Overall less powerful than Butter Knife, Kotter Knife
ANKO
ANKO
A DSL FOR LAYOUTS
Developed and maintained by Jetbrains, under Apache 2.0 license
The most important element of Anko is the Layout DSL
Idea: Replace XML layout definitions by Kotlin code - without having to build
the layout in a truly programmatic sense
Modular - as were talking about UI/Layout, its very important to select the
right library for your minSDKVersion
Extensible - you can add your own DSL elements for custom UI controls
ANKO
LAYOUT XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:gravity="center"
android:text="@string/empty_todos_message"
android:layout_weight="7"
android:layout_height="wrap_content" />
<Button
android:layout_width="match_parent"
android:layout_weight="1"
android:text="Say Hello"
android:layout_height="0dp" />
</LinearLayout>
ANKO
PROGRAMMATIC LAYOUT IN KOTLIN
val act = this
val layout = LinearLayout(act)
layout.orientation = LinearLayout.VERTICAL
val name = EditText(act)
val button = Button(act)
button.text = "Say Hello"
button.setOnClickListener {
Toast.makeText(act, "Hello, ${name.text}!", Toast.LENGTH_SHORT).show()
}
layout.addView(name)
layout.addView(button)
ANKO
ANKO DSL
verticalLayout {
val name = editText()
button("Say Hello") {
onClick { toast("Hello, ${name.text}!") }
}
}
ANKO
BUT THERES MORE (ANKO ADVANCED TOPICS)
Intent Wrappers for various purposes: e.g. sendSMS(number, [text])
Service shortcuts
Configuration qualifiers: configuration(screenSize = ScreenSize.LARGE,
orientation = Orientation.LANDSCAPE) { }
Asynchronous tasks
SQLLite
Removes all the tragic cursor handling and lot of the try/catch blocks necessary
LIBRARIES AND TOOLS
https://www.flickr.com/photos/sillygwailo/5990089210/
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
OVERVIEW
Kotter Knife
Butter Knife
KAndroid
Kovenant
Quickies: Fuel, Injekt, Spek, Kotson
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOTTER KNIFE
We dont like findByViewId() - read: https://ragunathjawahar.wordpress.com/
2015/03/23/kotlin-findviewbyid-dead-as-dinosaurs
Kotter Knife provides view binding in a similar way to Butter Knife for Android/
Java
Why Kotter Knife (runtime library) over Kotlin Android Extensions (compiler
plugin)?
Porting code from Java/Butter Knife to Kotlin
Features like listener binding and resources binding that dont exist in KAE.
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
BUTTER KNIFE
Not much to say about it, probably one of the most famous libraries in the
Android world.
Butter Knife was difficult to use with Kotlin in the beginning
Since Kotlin 1.0 RC you can in fact just use Butter Knife in your Kotlin code
Sample code for Butter Knife/Kotlin in the official Jetbrains Kotlin Examples
repo (https://github.com/JetBrains/kotlin-examples/tree/master/gradle/
android-butterknife)
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOTTER KNIFE VS BUTTER KNIFE VS KAE (I)
findViewById(R.id.send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("MainActivity", "onClick: send")
}
});
@OnClick(R.id.send)
void clickSend(View v) {
Log.d("MainActivity", "onClick: send")
}
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOTTER KNIFE VS BUTTER KNIFE VS KAE (II)
findViewById(R.id.send).setOnClickListener { view -> Log.d("MainActivity",
"onClick: send") };
val btnSend: Button by bindView(R.id.send)
btnSend.setOnClickListener({ view -> Log.d("MainActivity", "onClick: send") })
import kotlinx.android.synthetic.activity_main.*
btn_send.setOnClickListener({ view -> Log.d("MainActivity", "onClick: send") })
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KANDROID
KAndroid is an extension library for Kotlin/Android
Contains a variety of absolutely distinct and unconnected functionality
Common theme: lets get rid of boilerplate code
Apache 2.0 license
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KANDROID FEATURES
View binding (again) Dealing with Intents
TextWatcher SDK Version API (from/to)
SeekBar Extension Thread management
SearchView Extension
Shortcuts to system services
Logging
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KANDROID EXAMPLES
runDelayed(1000) {
// delayed execution
}
runDelayedOnUiThread(5000) {
// delayed UI update
}
toApi(16, inclusive = true) {
// handle devices running older APIs
}
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOVENANT
In a nutshell: Promises for Kotlin
Very modular built, you can essentially pick and choose the artifacts of
Kovenant that youd like to use - Kovenant is not an Android-specific library
Good staring set for Android: core, android, combine, jvm, functional
MIT license
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOVENANT FEATURES
Core, foundations of a Promise Functional: adds map, bind and
framework apply to support more advanced
HOF constructs in Kovenant
Tasks & Callbacks
JVM: Executors and Throttles (thread
Chaining (Then, ThenApply) pools)
Lazy Promises
Android: UI callbacks and interacting
Cancelling and Voiding with UI Thread
Combine: combines 2-20 promises
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOVENANT EXAMPLES (I)
task {
// some long-running thing
} success {
println("result: $it")
} fail {
println("problem: ${it.message}")
} always {
// this will always happen
}
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
KOVENANT EXAMPLES (II)
promiseOnUi {
// do some UI preparation
} then {
// the actual work
} successUi {
// update UI
}
OTHER LIBRARIES AND TOOLS FOR KOTLIN AND ANDROID
OVERVIEW
Kotter Knife
Butter Knife
KAndroid
Kovenant
Quickies: Fuel, Injekt, Spek, Kotson
FINAL THOUGHTS
https://www.flickr.com/photos/brickset/16099265973/
FINAL THOUGHTS
PERFORMANCE
Runtime is pretty much on-par with Java
Pre Kotlin 1.0.2: Build process is slower than a comparable app in Java - mainly
due to how the Kotlin compiler works (no partial builds/compilation)
Kotlin libraries do add to the size of the application as well as to the method
count
Kotlin runtime + stdlib are similar in method count to support-v4 or play-
services-base and add significantly less than Scala or Groovy
FINAL THOUGHTS
LANGUAGE AND MATURITY
Kotlin 1.0 was a big step for the language
Surprisingly mature for a 1.0 release (but 5+ years in the making)
Full of great concepts and idioms
Refreshing language that makes both Android and JVM development significantly
more pleasant and fun
Issue: Tooling around static analysis is non-existent at the moment (some basic listing
for Android is available since 1.0.2)
Ready for prime-time yet?
FINAL THOUGHTS
WHAT DID WE LEARN?
What is Kotlin?
Common idioms and language concepts
Kotlin and Android
Anko
Other libraries and tools for Kotlin and Android
RESOURCES
RESOURCES
Kotlin: http://kotlinlang.org
Anko: https://github.com/Kotlin/anko
Kotter Knife: https://github.com/JakeWharton/kotterknife
KAndroid: https://github.com/pawegio/KAndroid
Kovenant: https://github.com/mplatvoet/kovenant
Fuel: https://github.com/kittinunf/Fuel
Injekt: https://github.com/kohesive/injekt
Spek: http://jetbrains.github.io/spek/
Kotson: https://github.com/SalomonBrys/Kotson
RESOURCES
GET IN TOUCH
Kai Koenig
Email: kai@ventego-creative.co.nz
Twitter: @AgentK