Kotlin and Android Development
Kittinun Vantasin
Speaker
github.com/kittinunf
@kittinunf
Kotlin ... why?
Stuck on old Java (6-ish)
-
No javax.time
-
No streams API
-
No lambdas, method refs
ThreeTenAndroidBP
Standalone backport / RxJava
Retrolambda
Kotlin ... why?
Kotlin ... why?
Inherent Java language restrictions
-
Cannot add methods on platform types
-
Problem with null
-
Mutability is everywhere
-
Force to evolve everything around Object
Kotlin ... why?
Android restrictions
-
Large inheritance tree
-
Nullability usage
-
API ceremony
Kotlin
Statically typed programming language
for the JVM, Android and the browser
100% interoperable with Java™
Kotlin - Crash course
Null safety | Enum class | Immutability |
---|---|---|
Type Inference | Properties & Fields | Data class |
Lambda | Extension Functions | High order functions |
Type-safe builder | Collection APIs | Kotlin-Java Interoperable |
Null Safety
val nullableString: String? = null
//safe call
nullableString?.length
//NPE lovers
nullableString!!.length //throw NPE
fun doSomething(s: String) {}
//compile error
doSomething(nullableString)
fun doAnotherThing(s: String?) {}
//compile
doAnotherThing(nullabeString) {}
Type inference
val i: Int = 10
val j = 10 //type is infered
fun add(x: Int, y: Int): Int {
return x + y
}
fun add1(x: Int, y: Int) = x + y
val string: String? = "Hello"
println(string?.length) //need to use safe call(?:) operator
string?.let {
println(string.length) //?: is no longer needed
}
if (string != null) {
println(string.length) //here ?: is not needed
}
Extension Functions
//add extension function over Int
fun Int.fib(): Int {
var last = 0
var prev = 1
var result =
for (i in 2..this) {
result = last + prev
last = prev
prev = result
}
return if (this == 1) 1 else result
}
31.fib() //print 1346269
Lambda
val powOfTwo = { i: Int -> i * i } //type = (Int, Int) -> Int
println(powOfTwo(5)) //print 25
class Foo {
var value: String by Delegates.observable("")
{ meta, oldValue, newValue ->
updateListener?.invoke(newValue)
}
var updateListener: ((String) -> Unit)? = null
}
val f = Foo()
f.value = "v1"
f.updateListener = ::println
f.value = "v2" //print "v2"
f.value = "v3" //print "v3"
What does this mean to Android Developer?
Kotlin ❤️ Android
In the nutshell
Java
Kotlin
javac
kotlinc
Bytecode
Android
Kotlin Android Extension
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="John Appleseed"
/>
import kotlinx.android.synthetic.main.activity_main.*
class MyAwesomeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_awesome)
textView.text = "Hello Kotlin for Android"
}
}
SAM Conversion
import kotlinx.android.synthetic.main.activity_main.*
class MyAwesomeActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_my_awesome)
button.setOnClickListener {
println("do something useful")
}
}
}
//compiler shows you
public fun setOnClickListener(
listener: ((v: View) -> Unit)): Unit
Extension....
// get all the children in ViewGroup
fun ViewGroup.children(): List<View> =
(0..childCount - 1).map { getChildAt(it) }
// is View visible
val View.isVisible: Boolean = visibility == View.VISIBLE
// get locationManager in Context
val Context.locationManager: LocationManager
get() = getSystemService(Context.LOCATION_SERVICE) as LocationManager
fun TextView.textChangedListener(init: _TextWatcher.() -> Unit) {
val listener = _TextWatcher()
listener.init()
addTextChangedListener(listener)
}
class _TextWatcher : android.text.TextWatcher {
private var _beforeTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null
private var _onTextChanged: ((CharSequence?, Int, Int, Int) -> Unit)? = null
private var _afterTextChanged: ((android.text.Editable?) -> Unit)? = null
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
_beforeTextChanged?.invoke(s, start, count, after)
}
fun beforeTextChanged(listener: (CharSequence?, Int, Int, Int) -> Unit) {
_beforeTextChanged = listener
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
_onTextChanged?.invoke(s, start, before, count)
}
fun onTextChanged(listener: (CharSequence?, Int, Int, Int) -> Unit) {
_onTextChanged = listener
}
override fun afterTextChanged(s: android.text.Editable?) {
_afterTextChanged?.invoke(s)
}
fun afterTextChanged(listener: (android.text.Editable?) -> Unit) {
_afterTextChanged = listener
}
}
class MyAwesomeActivity : Activity() {
fun onCreate() {
super.onCreate()
textView.textChangedListener {
onTextChanged {
Log.d("onTextChanged", it.toString())
}
}
}
}
Supercharged API
inline fun SharedPreferences.edit(
build: SharedPreference.Editor.() -> Unit) {
val editor = edit()
editor.build()
editor.apply()
}
fun SharedPreferences.put(p: Pair<String, String>) {
val (first, second) = p
putString(first, second)
}
//usage
pref.edit {
put("username" to "foo")
put("userId" to "1234")
remove("bar")
}
Convinced ?
How Cookpad Team use Kotlin
Resources
Website and Documentation
https://kotlinlang.org/
Online Compiler
http://try.kotlinlang.org/
Hand-on learning
https://github.com/Kotlin/kotlin-koans
Q & A
Tell us what you think
https://goo.gl/GU8vK2
Kotlin and Android Development
By Kittinun Vantasin
Kotlin and Android Development
Slide for Android Talk @ Cookpad
- 2,210