KEMBAR78
Turbinando o desenvolvimento Android com Kotlin | PDF
Turbinando o
desenvolvimento Android
com Kotlin
+Nelson Glauber
@nglauber

www.nglauber.com.br
Porque Kotlin?
• Linguagem moderna, concisa, intuitiva e fácil de aprender.
• Open Source, mantido pela JetBrains
• 100% Interoperável com Java. Você pode possuir código Java e
Kotlin no mesmo projeto.
• Suporte nativo no Android Studio.
• Menos verboso. Você escreve menos código.
• Null Safety
• Possui recursos de linguagens funcionais
• Extension functions, funções de alta ordem e muito mais
build.gradle
buildscript {
ext.kotlin_version = '1.1.3-2'
repositories {
jcenter()
}
dependencies {
classpath ‘com.android.tools.build:gradle:2.3.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
...
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
...
}
...
build.gradle
Kotlin bytecode?
data class Person(
var name: String,
var age: Int) {
override fun toString(): String {
return "$name - $age"
}
}
Person.kt
Compiler

kotlinc
________________
________________
________________
________________
________________
________________
________________
Person.class
val (imutável)
var (mutável)
val hello: String = "hello"
val world = "world"
println("$hello $world")
world = "bla" // compilation error
var helloWorld: String = "Hello"
helloWorld = "Hello World"
println(helloWorld)
Tipos de dados
val i: Int = 7
// no automatic conversion
val d: Double = i.toDouble()
var c: Char = 'c'
val s = "Example"
c = s[2] // Char 'a'
val i1: Int = c.toInt()
val i2 = 12 // Int
val iHex = 0x0f // Int em hexadecimal
val l = 3L // Long
val d1 = 3.5 // Double
val f = 3.5F // Float
val any: Any = 3 // Any=Object
* Não existem tipos primitivos
Range
val x = 5
if (IntRange(1, 10).contains(x)) {
// do something
}
if (1.rangeTo(10).contains(x)) {
// do something
}
if ((1..10).contains(x)) {
// do something
}
if/else e when 

podem retornar valores
val max = if (a > b) a else b
val msg = when (x) {
in 1..10, 100 -> "x is in the range or is 100”
in validNumbers -> "x is valid"
!in 10..20 -> "x is outside the range"
else -> "none of the above"
}
try/catch também…
val content = try {
// load some data from file
return fileContent
} catch (e: Exception) {
return null
}
Importante! Kotlin não possui checked exceptions!
for
for (item in list) {
//... iterate over a list
}
for (i in 0..NUM_ROWS) {
//... i == NUM_ROWS
}
for (i in 0 until NUM_ROWS) {
//... i < NUM_ROWS
}
for (i in NUM_ROWS downTo 0) {
//... from NUM_ROWS to 0
}
for (i in 0..10 step 2) {
//... 0, 2, 4, 6, 8, 10
}
Métodos ou Funções?
// void = Unit
fun foo(text: String) : Unit {
println("Hi $text")
}
fun bar(text: String) {
println("Hey $text")
}
// more verbose method
fun sum1(x: Int, y: Int) : Int {
return x + y
}
// or simpler...
fun sum2(x:Int, y:Int): Int = x + y
// even simpler
fun sum3(x:Int, y:Int) = x + y
Parâmetros com valores
padrão
fun showMessage(title : String = "Hello",
name : String = "Glauber") {
println("$title $name")
}
// We can call this function using…
showMessage()
showMessage("Hey")
showMessage("Hello", "Nelson")
showMessage(name="José")
val employee = Employee("Nelson", 35, "99009900")
print("${employee.name} - " +
"${employee.age} / ${employee.id}")
Classes
open class Person(var name : String, var age : Int)
class Employee(name : String,
age : Int,
var id : String) : Person(name, age)
Classes
open class Person {
var name : String = ""
var age : Int = 0
}
class Employee(name : String,
age : Int,
var id : String) : Person() {
init {
this.name = name
this.age = age
}
}
val employee = Employee("Nelson", 35, "99009900")
print("${employee.name} - " +
"${employee.age} / ${employee.id}")
Classes
class Company {
init {
// Initialize some stuff...
}
constructor(name : String) {
// Initialize with name
}
constructor(id : Int) {
// Initialize with ID
}
}
Data Classes
data class Product(var name: String, var descr: String, var price: Float)
• Já possui as funções equals()/
hashCode()
• Já possui toString() no padrão

"Product(name=A, descr=B, price=42)”
• Já possui o método copy()
• destructuring functions correspondentes as
propriedades ordenadas por declaração
• Não pode ser estendida
p1 = Product("X", "Y", price = 10F)
p2 = p1.copy(price = 20F)
val (name, _, price) = p1
var p1 = Product("X", "Y", price = 10F)
var p2 = Product("X", "Y", price = 10F)
println(p1 == p2) // true
println(p1 === p2) // false
Interfaces
interface Foo {
val value : Int // must implement getter
fun sum(x : Int, y : Int) = x + y // default implementation
}
Modificadores de acesso
• public (padrão)
• private
• protected = private + subclasses

classes no mesmo pacote não acessam
• internal
• Não possui o modificador para package 😢
Properties
class Person {
var name : String = ""
get() = field.toUpperCase()
set(value) {
field = "Name: $value"
}
var age : Int = 0
}
Companion Object
int x = Foo.Companion.getCONSTANT_1();
int y = Foo.CONSTANT_2;
Person p = Foo.ROOT;
Foo.foo(); ☕
companion object {
val CONSTANT_1 = 1 // private + getter
const val CONSTANT_2 = 2 // public
@JvmField val ROOT = User("root”) // getROOT()
@JvmStatic fun foo() {}
}
Classes x Tipos
Class Type
String Yes Yes
String? No Yes
Person Yes Yes
Person? No Yes
String?
String
Null Safety
// Compilation error
var person: Person = null
// Now can be null
var personOpt: Person? = null
// Compilation error
println(pessoaOpt.nome)
// It works!
println(pessoaOpt?.nome)
Null Safety
// you can avoid the "?." Operator with a "if"
if (pessoaOpt != null) {
println(pessoaOpt.nome)
}
// Smell...
println(pessoaOpt!!.nome)
// Elvis still alive
val name = pessoaOpt?.nome ?: "empty"
Late Init
class MainActivity : AppCompatActivity() {
private lateinit var db: BookDatabase
...
Relaxa compilador, eu vou
inicializar esse atributo depois. 

Confia em mim! 😎
Cast
val text1 = param as String // may throw an exception
val text2 = param as? String // this is may be null
...
if (param is String) {
val text = param // smart cast!!
...
}
Null Safety
• Como conseguir um NullPointerException?
• Lançando a exceção explicitamente
• Usando o operador !!
• Acessando um atributo lateinit que não foi
inicializado
• Invocando código Java 😈
Extension Functions
fun String.withPlusInTheEnd() : String = this + "+"
"Glauber".withPlusInTheEnd()
fun Activity.showShortToast(text: String) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
}
Extension Properties
val <T> List<T>.lastIndex: Int
get() = size - 1
apply, with, let, run
• apply é uma extension function que executa
o bloco de código sobre uma instância e retorna a
própria instância. 
• with  não é uma extension function e o objeto
deve ser explicitamente passado como parâmetro.
O returno é o resultado do bloco da função.
apply, with, let, run
startActivity(Intent(activity, DetailActivity::class.java).apply {
putExtra("nome", "Glauber")
putExtra("idade", 33)
})
with(person) {
name = "Glauber"
age = 33
}
apply, with, let, run
• let é uma função de escopo muito usado para lidar
com nullable objects. Ao invés de encadear if-else,
você pode simplesmente combinar o
operador "?." com o let. Teremos então um lambda
onde o argumento é uma versão not-nullable do
objeto original.Por fim, o let retorna o resultado do
bloco.
• run é uma extension function e é algo como uma
junção do let e apply, A única diferença é o retorno: o
apply retorna o próprio objeto, enquanto que
o run retorna o resultado do bloco.
apply, with, let, run
val person : Person? =
intent.getSerializableExtra("person") as? Person
person?.let {
listOfPerson.add(person)
listOfPerson.sortBy { it.name }
adapter.notifyDataSetChanged()
}
val x = Person("Nelson", 33).run {
name.length + age
}
println(x) // 39
Synthetic Imports
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textViewMessage.text = "Hello world!"
}
...
apply plugin: 'kotlin-android-extensions'
Override

obrigatório
Lambdas
// Verbose
fabAdd.setOnClickListener(object : View.OnClickListener {
override fun onClick(v: View?) {
}
})
// Concise
fabAdd.setOnClickListener { view ->
}
opcional
Lambdas
listView.setOnItemClickListener { _, _, position, _ ->
showShortToast(listOfPerson[position].name)
}
Higher-Order Functions
class PersonAdapter(val people: List<Person>,
val callback: (Person) -> Unit) :
RecyclerView.Adapter<PersonHolder>() {
override fun onBindViewHolder(holder: PersonHolder?, position: Int) {
val person = people[position]
holder?.textView?.apply {
text = person.name
setOnClickListener { callback(person) }
}
}
Higher-Order Functions
override fun onCreate(savedInstanceState: Bundle?) {
...
var adapter = PersonAdapter(peopleList, this::onItemClick)
...
}
private fun onItemClick(person : Person) {
showShortToast(person.name)
}
override fun onCreate(savedInstanceState: Bundle?) {
...
var adapter = PersonAdapter(peopleList, { person ->
})
...
}
Typealias
typealias PersonCallback = (Person)->Unit
class PersonAdapter(val people: List<Person>,
val callback: PersonCallback)
: RecyclerView.Adapter<PersonHolder>() {
Operator overloading
+a a.unaryPlus()
-a a.unaryMinus()
!a a.not()
a++ a.inc()
a— a.dec()
a += b a.plusAssign(b)
a -= b a.minusAssign(b)
a *= b a.timesAssign(b)
a /= b a.divAssign(b)
a %= b a.modAssign(b)
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b)
a..b a.rangeTo(b)
a in b a.contains(b)
a > b a.compareTo(b) > 0
a < b a.compareTo(b) < 0
a >= b a.compareTo(b) >= 0
Operator overloading
operator fun String.times(b: Int): String {
val buffer = StringBuffer()
for (i in 1..b) {
buffer.append(this)
}
return buffer.toString()
}
val newString = "Test" * 4
Delegated Properties
class SomeClass {
var p: String by Delegate()
}
// ...
import kotlin.reflect.KProperty
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name} in $thisRef.'")
}
}
Lazy, Observable, Vetoable
val people: MutableList<Person> by lazy { mutableListOf<Person>() }
class User {
var email: String by Delegates.observable("") {
prop, old, new ->
//handle the change from old to new value
}
}
var positiveNumber = Delegates.vetoable(0) {
d, old, new ->
new >= 0
}
Mapeando um objeto com
um Map
class User(map: Map<String, Any?>) {
val name: String by map
val age: Int by map
}
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
Collections 😍
val list = listOf(1, 2, 3, 4, 5)
println(list[1])
val mutList = mutableListOf<Int>()
mutList.add(1)
val array = arrayOf("Nelson", "Glauber")
println(array[0])
val map = mapOf(1 to "Glauber", 2 to "Nelson", Pair(3, "Chico"))
println(map[1])
val mutMap = mutableMapOf<Int, String>()
mutMap.put(1, "João")
Collections 😍
• Agregate
• any, all, count, forEach, forEachIndexed,
max, min, none, sumBy, …
• Filtering
• filter, filterNot, slice, take, takeLast,
takeWhile, …
• Mapping
• flatMap, map, groupBy, mapIndexed, …
Collections 😍
• Elements
• contains, elementAt, first, indexOf, last,
lastIndexOf, single, …
• Generation operations
• merge, partition, plus, zip e unzip
• Ordering
• reverse, sort, sortBy, sortDescending e
sortDescendingBy
Collections 😍
val pessoas = listOf(
Pessoa("Nelson", 33),
Pessoa("Glauber", 33),
Pessoa("Ana", 27),
Pessoa("João", 12)
)
val p1 = pessoas.sortedBy { it.idade }
p1.forEach { println(it) }
val p2 = pessoas.maxBy { p -> p.idade }
println(p2)
val people = pessoas.groupBy { it.idade }
println("agrupado por idade: $people")
Collections 😍
// Return the set of cities the customers are from
fun getCitiesCustomersAreFrom(): Set<City> =
customers.map { customer -> customer.city }.toSet()
// Return a list of the customers who live in the given city
fun getCustomersFrom(city: City): List<Customer> =
customers.filter { customer -> customer.city == city }
Singletons com Object
object SilvioSantos {
fun mahOeee() = "Mah Ôeeee!"
fun juizo() = false
}
SilvioSantos.mahOeee()
if (SilvioSantos.juizo()) println("sem graça :(")
else println("Processo :’(")
infix
• Notação para chamada de
funções sem a necessidade de
usar “.” ou “( )”
• Devem ser "métodos" de uma
classe ou extension function.
• Só podem possuir um parâmetro
// Define extension to Int
infix fun Int.shl(x: Int): Int {
...
}
/* call extension function using
infix notation */
1 shl 2
// is the same as
1.shl(2)
Sealed classes
sealed class Operation {
class Add(val value: Int) : Operation()
class Substract(val value: Int) : Operation()
class Multiply(val value: Int) : Operation()
class Divide(val value: Int) : Operation()
}
fun execute(x: Int, op: Operation) = when (op) {
is Operation.Add -> x + op.value
is Operation.Substract -> x - op.value
is Operation.Multiply -> x * op.value
is Operation.Divide -> x / op.value
}
Coroutines + Anko
async(UI) {
val books = bg { loadBooksAsync() }
updateListView(books.await())
}
dependencies {
compile "org.jetbrains.anko:anko-coroutines:$anko_version"
}
// gradle.properties

kotlin.coroutines=enable
Curiosidades
• Você pode nomear seus imports usando “as"
• Você pode ter funções dentro de funções
• Você pode ter funções soltas em um arquivo, nesse
caso, será gerada uma classe com o nome do
arquivo, isso pode ser alterado usando
@file:JvmName(“SuaClasse”)
import com.mycompany.data.local.entity.Trip
import com.mycompany.model.Trip as TripModel
A IDE dá aquela forcinha…
• Aponta os erros e melhorias
• Ctrl-V de código Java faz a conversão automática
para Kotlin
• Ver bytecode do Kotlin e ver o Java
Prós
• Linguagem moderna, repleta de recursos e
facilidades não disponíveis no Java
• Suporte nativo do Android Studio.
• É muito fácil converter um código Java para Kotlin.
• Java e Kotlin podem co-existir no mesmo projeto.
• Não há overhead significante de performance do
Kotlin em comparação com o Java.
Contras
• A std library do Kotlin adicionará aproximadamente
300KB ao seu APK.
• Autocomplete demora um pouco mais.
• Compilação demora um pouco mais.
Learn more…
• Site Oficial (kotlinlang.org)
• Editor on-line (try.kotlinlang.org)
• Kotlin Koans (try.kotlinlang.org/koans)
• Antonio Leiva’s book (antonioleiva.com/google-kotlin)
• Como eu aprendi Kotlin (bit.do/nglauber_kotlin)
• Dominando o Android com Kotlin (em breve) 😉
Dúvidas?
@nglauber
+NelsonGlauber
www.nglauber.com.br

Turbinando o desenvolvimento Android com Kotlin

  • 1.
    Turbinando o desenvolvimento Android comKotlin +Nelson Glauber @nglauber
 www.nglauber.com.br
  • 2.
    Porque Kotlin? • Linguagemmoderna, concisa, intuitiva e fácil de aprender. • Open Source, mantido pela JetBrains • 100% Interoperável com Java. Você pode possuir código Java e Kotlin no mesmo projeto. • Suporte nativo no Android Studio. • Menos verboso. Você escreve menos código. • Null Safety • Possui recursos de linguagens funcionais • Extension functions, funções de alta ordem e muito mais
  • 6.
    build.gradle buildscript { ext.kotlin_version ='1.1.3-2' repositories { jcenter() } dependencies { classpath ‘com.android.tools.build:gradle:2.3.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
  • 7.
    apply plugin: 'com.android.application' applyplugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' android { ... sourceSets { main.java.srcDirs += 'src/main/kotlin' } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" ... } ... build.gradle
  • 8.
    Kotlin bytecode? data classPerson( var name: String, var age: Int) { override fun toString(): String { return "$name - $age" } } Person.kt Compiler
 kotlinc ________________ ________________ ________________ ________________ ________________ ________________ ________________ Person.class
  • 9.
    val (imutável) var (mutável) valhello: String = "hello" val world = "world" println("$hello $world") world = "bla" // compilation error var helloWorld: String = "Hello" helloWorld = "Hello World" println(helloWorld)
  • 10.
    Tipos de dados vali: Int = 7 // no automatic conversion val d: Double = i.toDouble() var c: Char = 'c' val s = "Example" c = s[2] // Char 'a' val i1: Int = c.toInt() val i2 = 12 // Int val iHex = 0x0f // Int em hexadecimal val l = 3L // Long val d1 = 3.5 // Double val f = 3.5F // Float val any: Any = 3 // Any=Object * Não existem tipos primitivos
  • 11.
    Range val x =5 if (IntRange(1, 10).contains(x)) { // do something } if (1.rangeTo(10).contains(x)) { // do something } if ((1..10).contains(x)) { // do something }
  • 12.
    if/else e when
 podem retornar valores val max = if (a > b) a else b val msg = when (x) { in 1..10, 100 -> "x is in the range or is 100” in validNumbers -> "x is valid" !in 10..20 -> "x is outside the range" else -> "none of the above" }
  • 13.
    try/catch também… val content= try { // load some data from file return fileContent } catch (e: Exception) { return null } Importante! Kotlin não possui checked exceptions!
  • 14.
    for for (item inlist) { //... iterate over a list } for (i in 0..NUM_ROWS) { //... i == NUM_ROWS } for (i in 0 until NUM_ROWS) { //... i < NUM_ROWS } for (i in NUM_ROWS downTo 0) { //... from NUM_ROWS to 0 } for (i in 0..10 step 2) { //... 0, 2, 4, 6, 8, 10 }
  • 15.
    Métodos ou Funções? //void = Unit fun foo(text: String) : Unit { println("Hi $text") } fun bar(text: String) { println("Hey $text") } // more verbose method fun sum1(x: Int, y: Int) : Int { return x + y } // or simpler... fun sum2(x:Int, y:Int): Int = x + y // even simpler fun sum3(x:Int, y:Int) = x + y
  • 16.
    Parâmetros com valores padrão funshowMessage(title : String = "Hello", name : String = "Glauber") { println("$title $name") } // We can call this function using… showMessage() showMessage("Hey") showMessage("Hello", "Nelson") showMessage(name="José")
  • 17.
    val employee =Employee("Nelson", 35, "99009900") print("${employee.name} - " + "${employee.age} / ${employee.id}") Classes open class Person(var name : String, var age : Int) class Employee(name : String, age : Int, var id : String) : Person(name, age)
  • 18.
    Classes open class Person{ var name : String = "" var age : Int = 0 } class Employee(name : String, age : Int, var id : String) : Person() { init { this.name = name this.age = age } } val employee = Employee("Nelson", 35, "99009900") print("${employee.name} - " + "${employee.age} / ${employee.id}")
  • 19.
    Classes class Company { init{ // Initialize some stuff... } constructor(name : String) { // Initialize with name } constructor(id : Int) { // Initialize with ID } }
  • 20.
    Data Classes data classProduct(var name: String, var descr: String, var price: Float) • Já possui as funções equals()/ hashCode() • Já possui toString() no padrão
 "Product(name=A, descr=B, price=42)” • Já possui o método copy() • destructuring functions correspondentes as propriedades ordenadas por declaração • Não pode ser estendida p1 = Product("X", "Y", price = 10F) p2 = p1.copy(price = 20F) val (name, _, price) = p1 var p1 = Product("X", "Y", price = 10F) var p2 = Product("X", "Y", price = 10F) println(p1 == p2) // true println(p1 === p2) // false
  • 21.
    Interfaces interface Foo { valvalue : Int // must implement getter fun sum(x : Int, y : Int) = x + y // default implementation }
  • 22.
    Modificadores de acesso •public (padrão) • private • protected = private + subclasses
 classes no mesmo pacote não acessam • internal • Não possui o modificador para package 😢
  • 23.
    Properties class Person { varname : String = "" get() = field.toUpperCase() set(value) { field = "Name: $value" } var age : Int = 0 }
  • 24.
    Companion Object int x= Foo.Companion.getCONSTANT_1(); int y = Foo.CONSTANT_2; Person p = Foo.ROOT; Foo.foo(); ☕ companion object { val CONSTANT_1 = 1 // private + getter const val CONSTANT_2 = 2 // public @JvmField val ROOT = User("root”) // getROOT() @JvmStatic fun foo() {} }
  • 25.
    Classes x Tipos ClassType String Yes Yes String? No Yes Person Yes Yes Person? No Yes String? String
  • 26.
    Null Safety // Compilationerror var person: Person = null // Now can be null var personOpt: Person? = null // Compilation error println(pessoaOpt.nome) // It works! println(pessoaOpt?.nome)
  • 27.
    Null Safety // youcan avoid the "?." Operator with a "if" if (pessoaOpt != null) { println(pessoaOpt.nome) } // Smell... println(pessoaOpt!!.nome) // Elvis still alive val name = pessoaOpt?.nome ?: "empty"
  • 28.
    Late Init class MainActivity: AppCompatActivity() { private lateinit var db: BookDatabase ... Relaxa compilador, eu vou inicializar esse atributo depois. 
 Confia em mim! 😎
  • 29.
    Cast val text1 =param as String // may throw an exception val text2 = param as? String // this is may be null ... if (param is String) { val text = param // smart cast!! ... }
  • 30.
    Null Safety • Comoconseguir um NullPointerException? • Lançando a exceção explicitamente • Usando o operador !! • Acessando um atributo lateinit que não foi inicializado • Invocando código Java 😈
  • 31.
    Extension Functions fun String.withPlusInTheEnd(): String = this + "+" "Glauber".withPlusInTheEnd() fun Activity.showShortToast(text: String) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() }
  • 32.
    Extension Properties val <T>List<T>.lastIndex: Int get() = size - 1
  • 33.
    apply, with, let,run • apply é uma extension function que executa o bloco de código sobre uma instância e retorna a própria instância.  • with  não é uma extension function e o objeto deve ser explicitamente passado como parâmetro. O returno é o resultado do bloco da função.
  • 34.
    apply, with, let,run startActivity(Intent(activity, DetailActivity::class.java).apply { putExtra("nome", "Glauber") putExtra("idade", 33) }) with(person) { name = "Glauber" age = 33 }
  • 35.
    apply, with, let,run • let é uma função de escopo muito usado para lidar com nullable objects. Ao invés de encadear if-else, você pode simplesmente combinar o operador "?." com o let. Teremos então um lambda onde o argumento é uma versão not-nullable do objeto original.Por fim, o let retorna o resultado do bloco. • run é uma extension function e é algo como uma junção do let e apply, A única diferença é o retorno: o apply retorna o próprio objeto, enquanto que o run retorna o resultado do bloco.
  • 36.
    apply, with, let,run val person : Person? = intent.getSerializableExtra("person") as? Person person?.let { listOfPerson.add(person) listOfPerson.sortBy { it.name } adapter.notifyDataSetChanged() } val x = Person("Nelson", 33).run { name.length + age } println(x) // 39
  • 37.
    Synthetic Imports import kotlinx.android.synthetic.main.activity_main.* classMainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) textViewMessage.text = "Hello world!" } ... apply plugin: 'kotlin-android-extensions' Override
 obrigatório
  • 38.
    Lambdas // Verbose fabAdd.setOnClickListener(object :View.OnClickListener { override fun onClick(v: View?) { } }) // Concise fabAdd.setOnClickListener { view -> } opcional
  • 39.
    Lambdas listView.setOnItemClickListener { _,_, position, _ -> showShortToast(listOfPerson[position].name) }
  • 40.
    Higher-Order Functions class PersonAdapter(valpeople: List<Person>, val callback: (Person) -> Unit) : RecyclerView.Adapter<PersonHolder>() { override fun onBindViewHolder(holder: PersonHolder?, position: Int) { val person = people[position] holder?.textView?.apply { text = person.name setOnClickListener { callback(person) } } }
  • 41.
    Higher-Order Functions override funonCreate(savedInstanceState: Bundle?) { ... var adapter = PersonAdapter(peopleList, this::onItemClick) ... } private fun onItemClick(person : Person) { showShortToast(person.name) } override fun onCreate(savedInstanceState: Bundle?) { ... var adapter = PersonAdapter(peopleList, { person -> }) ... }
  • 42.
    Typealias typealias PersonCallback =(Person)->Unit class PersonAdapter(val people: List<Person>, val callback: PersonCallback) : RecyclerView.Adapter<PersonHolder>() {
  • 43.
    Operator overloading +a a.unaryPlus() -aa.unaryMinus() !a a.not() a++ a.inc() a— a.dec() a += b a.plusAssign(b) a -= b a.minusAssign(b) a *= b a.timesAssign(b) a /= b a.divAssign(b) a %= b a.modAssign(b) a + b a.plus(b) a - b a.minus(b) a * b a.times(b) a / b a.div(b) a % b a.rem(b) a..b a.rangeTo(b) a in b a.contains(b) a > b a.compareTo(b) > 0 a < b a.compareTo(b) < 0 a >= b a.compareTo(b) >= 0
  • 44.
    Operator overloading operator funString.times(b: Int): String { val buffer = StringBuffer() for (i in 1..b) { buffer.append(this) } return buffer.toString() } val newString = "Test" * 4
  • 45.
    Delegated Properties class SomeClass{ var p: String by Delegate() } // ... import kotlin.reflect.KProperty class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }
  • 46.
    Lazy, Observable, Vetoable valpeople: MutableList<Person> by lazy { mutableListOf<Person>() } class User { var email: String by Delegates.observable("") { prop, old, new -> //handle the change from old to new value } } var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }
  • 47.
    Mapeando um objetocom um Map class User(map: Map<String, Any?>) { val name: String by map val age: Int by map } val user = User(mapOf( "name" to "John Doe", "age" to 25 ))
  • 48.
    Collections 😍 val list= listOf(1, 2, 3, 4, 5) println(list[1]) val mutList = mutableListOf<Int>() mutList.add(1) val array = arrayOf("Nelson", "Glauber") println(array[0]) val map = mapOf(1 to "Glauber", 2 to "Nelson", Pair(3, "Chico")) println(map[1]) val mutMap = mutableMapOf<Int, String>() mutMap.put(1, "João")
  • 49.
    Collections 😍 • Agregate •any, all, count, forEach, forEachIndexed, max, min, none, sumBy, … • Filtering • filter, filterNot, slice, take, takeLast, takeWhile, … • Mapping • flatMap, map, groupBy, mapIndexed, …
  • 50.
    Collections 😍 • Elements •contains, elementAt, first, indexOf, last, lastIndexOf, single, … • Generation operations • merge, partition, plus, zip e unzip • Ordering • reverse, sort, sortBy, sortDescending e sortDescendingBy
  • 51.
    Collections 😍 val pessoas= listOf( Pessoa("Nelson", 33), Pessoa("Glauber", 33), Pessoa("Ana", 27), Pessoa("João", 12) ) val p1 = pessoas.sortedBy { it.idade } p1.forEach { println(it) } val p2 = pessoas.maxBy { p -> p.idade } println(p2) val people = pessoas.groupBy { it.idade } println("agrupado por idade: $people")
  • 52.
    Collections 😍 // Returnthe set of cities the customers are from fun getCitiesCustomersAreFrom(): Set<City> = customers.map { customer -> customer.city }.toSet() // Return a list of the customers who live in the given city fun getCustomersFrom(city: City): List<Customer> = customers.filter { customer -> customer.city == city }
  • 53.
    Singletons com Object objectSilvioSantos { fun mahOeee() = "Mah Ôeeee!" fun juizo() = false } SilvioSantos.mahOeee() if (SilvioSantos.juizo()) println("sem graça :(") else println("Processo :’(")
  • 54.
    infix • Notação parachamada de funções sem a necessidade de usar “.” ou “( )” • Devem ser "métodos" de uma classe ou extension function. • Só podem possuir um parâmetro // Define extension to Int infix fun Int.shl(x: Int): Int { ... } /* call extension function using infix notation */ 1 shl 2 // is the same as 1.shl(2)
  • 55.
    Sealed classes sealed classOperation { class Add(val value: Int) : Operation() class Substract(val value: Int) : Operation() class Multiply(val value: Int) : Operation() class Divide(val value: Int) : Operation() } fun execute(x: Int, op: Operation) = when (op) { is Operation.Add -> x + op.value is Operation.Substract -> x - op.value is Operation.Multiply -> x * op.value is Operation.Divide -> x / op.value }
  • 56.
    Coroutines + Anko async(UI){ val books = bg { loadBooksAsync() } updateListView(books.await()) } dependencies { compile "org.jetbrains.anko:anko-coroutines:$anko_version" } // gradle.properties
 kotlin.coroutines=enable
  • 57.
    Curiosidades • Você podenomear seus imports usando “as" • Você pode ter funções dentro de funções • Você pode ter funções soltas em um arquivo, nesse caso, será gerada uma classe com o nome do arquivo, isso pode ser alterado usando @file:JvmName(“SuaClasse”) import com.mycompany.data.local.entity.Trip import com.mycompany.model.Trip as TripModel
  • 58.
    A IDE dáaquela forcinha… • Aponta os erros e melhorias • Ctrl-V de código Java faz a conversão automática para Kotlin • Ver bytecode do Kotlin e ver o Java
  • 59.
    Prós • Linguagem moderna,repleta de recursos e facilidades não disponíveis no Java • Suporte nativo do Android Studio. • É muito fácil converter um código Java para Kotlin. • Java e Kotlin podem co-existir no mesmo projeto. • Não há overhead significante de performance do Kotlin em comparação com o Java.
  • 60.
    Contras • A stdlibrary do Kotlin adicionará aproximadamente 300KB ao seu APK. • Autocomplete demora um pouco mais. • Compilação demora um pouco mais.
  • 62.
    Learn more… • SiteOficial (kotlinlang.org) • Editor on-line (try.kotlinlang.org) • Kotlin Koans (try.kotlinlang.org/koans) • Antonio Leiva’s book (antonioleiva.com/google-kotlin) • Como eu aprendi Kotlin (bit.do/nglauber_kotlin) • Dominando o Android com Kotlin (em breve) 😉
  • 63.
  • 64.