SlideShare a Scribd company logo
Mastering
Kotlin Standard
Library
Nelson Glauber
@nglauber
• Provides the essential types, classes and functions for
everyday work with Kotlin.
• In version 1.3 it contains approximately 50 sub packages
organized in 4 categories: 

Common, JVM, JS and Native.
Kotlin Std Lib
• Provides the essential types, classes and functions for
everyday work with Kotlin.
• In version 1.3 it contains approximately 50 sub packages
organized in 4 categories: 

Common, JVM, JS and Native.
Kotlin Std Lib
Scope Functions
• T.let { }
• T.apply { }
• T.also { }
• T.run { }
• run { }
• with(T) { }
Scope Functions
• It’s an extension function.

• Caller is represented by it.

• Returns the block’s last line.
• It’s commonly used for nullability checking.
public inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
fun deleteTempPhoto() {
var tempImageFile: File? = // ...
tempImageFile?.let {
if (it.exists()) it.delete()
}
}
fun deleteTempPhoto() {
var tempImageFile: File? = // ...
if (tempImageFile != null) {
if (tempImageFile.exists()) // thanks smart cast!
tempImageFile.delete()
}
}
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
if (tempImageFile != null && tempImageFile.exists())
tempImageFile.delete()
}
}
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
if (tempImageFile != null && tempImageFile.exists())
tempImageFile.delete()
}
}
Smart	cast	to	'File'	is	impossible,		
	because	'tempImageFile'	is	a	mutable		
	property	that	could	have	been	changed		
	by	this	time	
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
if (tempImageFile != null && tempImageFile.exists())
tempImageFile.delete()
}
}
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
if (tempImageFile != null && tempImageFile?.exists() == true )
tempImageFile?.delete()
}
}
😒😱
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
tempImageFile?.let {
if (it.exists()) it.delete()
}
}
}
class SomeClass {
var tempImageFile: File? = null
fun deleteTempPhoto() {
tempImageFile?.let { file ->
if (file.exists()) file.delete()
}
}
}
😎
• It’s an extension function.

• Caller is represented by this.

• Returns the caller itself (this).
• It’s commonly used for initializing and configuring an
object.
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
val chip = Chip(this)
chip.text = weatherType.name.capitalize()
chip.setChipBackgroundColorResource(R.color.colorAccent)
chip.isClickable = false
chip.isCheckable = false
chip.isCloseIconVisible = true
chip.setOnCloseIconClickListener {
if (viewModel.unselectWeatherType(weatherType)) {
chipGroup.removeView(it)
}
}
chipGroup.addView(chip)
val chip = Chip(this)
chip.text = weatherType.name.capitalize()
chip.setChipBackgroundColorResource(R.color.colorAccent)
chip.isClickable = false
chip.isCheckable = false
chip.isCloseIconVisible = true
chip.setOnCloseIconClickListener {
if (viewModel.unselectWeatherType(weatherType)) {
chipGroup.removeView(it)
}
}
chipGroup.addView(chip)
val chip = Chip(this).apply {
text = weatherType.name.capitalize()
setChipBackgroundColorResource(R.color.colorAccent)
isClickable = false
isCheckable = false
isCloseIconVisible = true
setOnCloseIconClickListener {
if (viewModel.unselectWeatherType(weatherType)) {
chipGroup.removeView(it)
}
}
}
chipGroup.addView(chip)
• It’s an extension function.

• Caller is represented by it.

• Returns the caller itself (this).
• It’s commonly used for chaining object initialization or
simple to separate one action from another.
public inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
val chip = Chip(this).apply {
text = weatherType.name.capitalize()
setChipBackgroundColorResource(R.color.colorAccent)
isClickable = false
isCheckable = false
isCloseIconVisible = true
setOnCloseIconClickListener {
if (viewModel.unselectWeatherType(weatherType)) {
chipGroup.removeView(it)
}
}
}
chipGroup.addView(chip)
Chip(this).apply {
text = weatherType.name.capitalize()
setChipBackgroundColorResource(R.color.colorAccent)
isClickable = false
isCheckable = false
isCloseIconVisible = true
setOnCloseIconClickListener {
if (viewModel.unselectWeatherType(weatherType)) {
chipGroup.removeView(it)
}
}
}.also {
chipGroup.addView(it)
}
• It’s an extension function.

• Caller is represented by this.

• Returns the block’s last line.
• It’s commonly used to get the result of an operation
using an object.
public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
public inline fun <R> run(block: () -> R): R {
return block()
}
• It’s not an extension function.

• There’s no reference to the caller (once it’s not an
extension function).

• Returns the block’s last line.
• It’s commonly used to get the result of an operation.
private fun getFavoriteCity(): String {
val prefs =
PreferenceManager.getDefaultSharedPreferences(this)
return prefs.getString("favCity", null) ?:
getString(R.string.pref_city_default)
}
private fun getFavoriteCity() =
PreferenceManager.getDefaultSharedPreferences(this).run {
getString("favCity", null)
} ?: run {
getString(R.string.pref_city_default)
}
• It’s not an extension function.

• The caller is passed as parameter and is referenced by
this.

• Returns the block’s last line.
• It’s commonly used when you want to remember Delphi.
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
val webView: WebView = loadWebView()
with(webView) {
settings.javaScriptEnabled = true
loadUrl("file:///android_asset/app_page.html")
}
val webView: WebView? = loadWebView()
with(webView) {
settings.javaScriptEnabled = true
loadUrl("file:///android_asset/app_page.html")
}
val webView: WebView? = loadWebView()
with(webView) {
settings.javaScriptEnabled = true
loadUrl("file:///android_asset/app_page.html")
}
	Only	safe	(?.)	or	non-null	asserted	(!!.)		
	calls	are	allowed	on	a	nullable	receiver		
	of	type	WebView?
val webView: WebView? = loadWebView()
with(webView) {
this?.settings?.javaScriptEnabled = true
this?.loadUrl("file:///android_asset/app_page.html")
}
😩
val webView: WebView? = loadWebView()
webView?.let {
it.settings.javaScriptEnabled = true
it.loadUrl("file:///android_asset/app_page.html")
}
%
• T.let { } for nullability check.
• T.apply { } for object initialization.
• T.also { } for initialization chaining or a simple change of
scope.
• T.run { } to get a result from an object sequence of calls.
• run { } to get a result from a sequence of calls.
• with(T) { } for some reason you don’t know how to
explain… :)
Scope Functions - Summary
Annotations
fun sayHello() {
println("Hello!")
}
fun sayHello() {
println("Hello!")
}
fun greetings(message: String = "Hello") {
println(message)
}
@Deprecated(
message = "This function is being replaced.",
replaceWith = ReplaceWith("greetings(message)"),
level = DeprecationLevel.WARNING)
fun sayHello() {
println("Hello!")
}
fun greetings(message: String = "Hello") {
println(message)
}
@Deprecated(
message = "This function is being replaced.",
replaceWith = ReplaceWith("greetings(message)"),
level = DeprecationLevel.WARNING)
fun sayHello() {
println("Hello!")
}
fun greetings(message: String = "Hello") {
println(message)
}
fun main() {
sayHello()
}
fun login(userName: String, password: String) {
// Do login
}
fun login(userName: String, password: String) {
// Do login
}
data class AuthUser(val name: String, val password: String)
fun login(authUser: AuthUser) {
// New login with user
}
fun login(userName: String, password: String) {
// Do login
}
@Experimental(Experimental.Level.WARNING)
annotation class NewApi
data class AuthUser(val name: String, val password: String)
fun login(authUser: AuthUser) {
// New login with user
}
fun login(userName: String, password: String) {
// Do login
}
@Experimental(Experimental.Level.WARNING)
annotation class NewApi
@NewApi
data class AuthUser(val name: String, val password: String)
@NewApi
fun login(authUser: AuthUser) {
// New login with user
}
fun login(userName: String, password: String) {
// Do login
}
@Experimental(Experimental.Level.WARNING)
annotation class NewApi
@NewApi
data class AuthUser(val name: String, val password: String)
@NewApi
fun login(authUser: AuthUser) {
// New login with user
}
@UseExperimental(NewApi::class)
fun main() {
login(AuthUser("ngvl", "123"))
}
• JvmStatic
• JvmOverloads
• JvmName
• JvmField
• Throws
@Jvm* annotations
object UserRepository {
fun insertUser(user: User) {
// insert user
}
}
object UserRepository {
fun insertUser(user: User) {
// insert user
}
}
public class MyJavaClass {
...
public void addUser() {
UserRepository.INSTANCE.insertUser(new User("Nelson"));
}
}
object UserRepository {
@JvmStatic
fun insertUser(user: User) {
// insert user
}
}
public class MyJavaClass {
...
public void addUser() {
UserRepository.INSTANCE.insertUser(new User("Nelson"));
}
}
object UserRepository {
@JvmStatic
fun insertUser(user: User) {
// insert user
}
}
public class MyJavaClass {
...
public void addUser() {
UserRepository.insertUser(new User("Nelson"));
}
}
class MyKotlinClass {
fun printName(name: String = "Anonymous") {
println("Hello $name!")
}
//...
}
class MyKotlinClass {
fun printName(name: String = "Anonymous") {
println("Hello $name!")
}
//...
}
MyKotlinClass instance = new MyKotlinClass();
instance.printName("Nelson"); // Works!
instance.printName(); // Error!
class MyKotlinClass {
@JvmOverloads
fun printName(name: String = "Anonymous") {
println("Hello $name!")
}
//...
}
class MyKotlinClass {
@JvmOverloads
fun printName(name: String = "Anonymous") {
println("Hello $name!")
}
//...
}
MyKotlinClass instance = new MyKotlinClass();
instance.printName("Nelson");
instance.printName();
public class MyCustomView extends LinearLayout {
public MyCustomView(Context context) {
super(context);
}
public MyCustomView(Context context,
@Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyCustomView(Context context,
@Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
...
}
class MyCustomView : LinearLayout {
constructor(context: Context) : super(context) {
}
constructor(context: Context,
attrs: AttributeSet?
) : super(context, attrs) {
}
constructor(context: Context,
attrs: AttributeSet?,
defStyleAttr: Int
) : super(context, attrs, defStyleAttr) {
}
class MyCustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
...
}
class ToggleView {
private var onOff = false
fun switch() {
onOff = !onOff
}
}
ToggleView toggleView = new ToggleView();
toggleView.switch(); // error!
class ToggleView {
private var onOff = false
@JvmName("switchOnOff")
fun switch() {
onOff = !onOff
}
}
ToggleView toggleView = new ToggleView();
toggleView.switchOnOff();
// StringsExtensions.kt
package ngvl.kotlin.demo.string
fun String.shouldCapitalizeName() =
this !in listOf("da", "das", "de", "di", "do", "dos")
fun String.capitalizeName() =
this.split(" ")
.joinToString(" ") {
if (it.shouldCapitalizeName())
it.capitalize()
else it
}
// Some Java file...
String name = StringExtensionsKt.capitalizeName("nelson glauber");
// StringsExtensions.kt
@file:JvmName("StringExt")
package ngvl.kotlin.demo.string
fun String.shouldCapitalizeName() =
this !in listOf("da", "das", "de", "di", "do", "dos")
fun String.capitalizeName() =
this.split(" ")
.joinToString(" ") {
if (it.shouldCapitalizeName())
it.capitalize()
else it
}
// Some Java file...
String name = StringExtensionsKt.capitalizeName("nelson glauber");
// StringsExtensions.kt
@file:JvmName("StringExt")
package ngvl.kotlin.demo.string
fun String.shouldCapitalizeName() =
this !in listOf("da", "das", "de", "di", "do", "dos")
fun String.capitalizeName() =
this.split(" ")
.joinToString(" ") {
if (it.shouldCapitalizeName())
it.capitalize()
else it
}
// Some Java file...
String name = StringExt.capitalizeName("nelson glauber");
data class Product(
val id: String,
val description: String,
val price: Float = 0f
)
Product product = new Product("001", "Smartphone", 0f);
System.out.println(
product.getId() +" - "+
product.getDescription() +" = "+
product.getPrice()
);
Product product = new Product("001", "Smartphone", 0f);
System.out.println(
product.getId() +" - "+
product.getDescription() +" = "+
product.getPrice()
);
data class Product(
@JvmField val id: String,
@JvmField val description: String,
@JvmField val price: Float = 0f
)
data class Product(
@JvmField val id: String,
@JvmField val description: String,
@JvmField val price: Float = 0f
)
Product product = new Product("001", "Smartphone", 0f);
System.out.println(
product.id +" - "+
product.description +" = "+
product.price
);
class MyKotlinClass {
companion object {
val CONSTANT_1 = 1
const val CONSTANT_2 = 2
@JvmField val CONSTANT_3 = 3
@JvmField val ROOT = User("root")
}
}
MyKotlinClass.Companion.getCONSTANT_1();
MyKotlinClass.CONSTANT_2;
MyKotlinClass.CONSTANT_3;
MyKotlinClass.ROOT;
object UserRepository {
@JvmStatic
fun insertUser(user: User) {
if (user.name.length < 5)
throw NameTooShortException()
// insert user ...
}
}
UserRepository.insertUser(new User("ngvl"));
object UserRepository {
@JvmStatic
@Throws(NameTooShortException::class)
fun insertUser(user: User) {
if (user.name.length < 5) {
throw NameTooShortException()
}
// insert user ...
}
}
UserRepository.insertUser(new User("ngvl"));
try {
UserRepository.insertUser(new User("ngvl"));
} catch (NameTooShortException e) {
// handle name too short
}
object UserRepository {
@JvmStatic
@Throws(NameTooShortException::class)
fun insertUser(user: User) {
if (user.name.length < 5) {
throw NameTooShortException()
}
// insert user ...
}
}
data class Recipe(
var name: String? = null,
var ingredients: List<Ingredient> = mutableListOf()
)
data class Ingredient(
var description: String? = null,
var quantity: Int = 0,
var unity: String? = null
)
data class Recipe(
var name: String? = null,
var ingredients: List<Ingredient> = mutableListOf()
)
data class Ingredient(
var description: String? = null,
var quantity: Int = 0,
var unity: String? = null
)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
val recipe = recipe {
name = "Chocolate Cake"
ingredient {
name = "Flour"
quantity = 3
unity = "cups"
}
}
println(recipe)
Recipe(name=Flour,	ingredients=[	
				Ingredient(description=null,	quantity=3,	unity=cups)]	
) 🤔
data class Recipe(
var name: String? = null,
var ingredients: List<Ingredient> = mutableListOf()
)
data class Ingredient(
var description: String? = null,
var quantity: Int = 0,
var unity: String? = null
)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
@DslMarker annotation class RecipeLang
@RecipeLang
data class Recipe(
var name: String? = null,
var ingredients: List<Ingredient> = mutableListOf()
)
@RecipeLang
data class Ingredient(
var description: String? = null,
var quantity: Int = 0,
var unity: String? = null
)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
val recipe = recipe {
name = "Chocolate Cake"
ingredient {
name = "Flour"
quantity = 3
unity = "cups"
}
}
println(recipe)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
Compile	error:	'var	name:	String?'		
can't	be	called	in	this	context	by		
implicit	receiver.		
Use	the	explicit	one	if	necessary
val recipe = recipe {
name = "Chocolate Cake"
ingredient {
this@recipe.name = "Choc.Cake"
quantity = 3
unity = "cups"
}
}
println(recipe)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
val recipe = recipe {
name = "Chocolate Cake"
ingredient {
description = "Flour"
quantity = 3
unity = "cups"
}
}
println(recipe)
fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build)
fun Recipe.ingredient(build: Ingredient.() -> Unit) {
ingredients += Ingredient().apply(build)
}
Recipe(name=Chocolate	Cake,	ingredients=[	
				Ingredient(description=Flour,	quantity=3,	unity=cups)]	
) 😋
• @Deprecated and @Experimental help to document the
evolution of your code
• @Jvm* annotations help the integration with Java code.
• @DslMarker create scopes for your DSLs.
Annotations - Summary
Delegates
abstract class Individual(
val name: String,
val surname: String,
val age: Int
)
class Student(
name: String,
surname: String,
age: Int,
val university: String
) : Individual(name, surname, age)
class Worker(
name: String,
surname: String,
age: Int,
val company: String
) : Individual(name, surname, age)
abstract class Individual(
val name: String,
val surname: String,
val age: Int
)
class Student(
name: String,
surname: String,
age: Int,
val university: String
) : Individual(name, surname, age)
class Worker(
name: String,
surname: String,
age: Int,
val company: String
) : Individual(name, surname, age)
interface Individual {
val name: String
val surname: String
val age: Int
}
data class IndividualData(
override val name: String,
override val surname: String,
override val age: Int
) : Individual
data class Student(
val data: IndividualData,
val university: String
) : Individual by data
data class Worker(
val data: IndividualData,
val company: String
) : Individual by data
interface Individual {
val name: String
val surname: String
val age: Int
}
data class IndividualData(
override val name: String,
override val surname: String,
override val age: Int
) : Individual
data class Student(
val data: IndividualData,
val university: String
) : Individual by data
data class Worker(
val data: IndividualData,
val company: String
) : Individual by data
val student = Student(
IndividualData("Nelson", "Leal", 36), "Universo"
)
student.run {
println("$name $surname - $age - $university")
}
	Nelson	Leal	-	36	-	Universo
class Repository {
private val peopleDAO: PeopleDAO by lazy {
Database.getPeopleDAO()
}
fun insert(person: Person) {
peopleDAO.add(person)
}
fun all(): List<Person> = peopleDAO.list()
}
class Repository {
private val peopleDAO: PeopleDAO by lazy {
Database.getPeopleDAO()
}
fun insert(person: Person) {
peopleDAO.add(person)
}
fun all(): List<Person> = peopleDAO.list()
}
class Repository {
private val peopleDAO: PeopleDAO by lazy {
Database.getPeopleDAO()
}
fun insert(person: Person) {
peopleDAO.add(person)
}
fun all(): List<Person> = peopleDAO.list()
}
val repo = Repository()
repo.insert(Person("1", "Nelson"))
repo.insert(Person("2", "Glauber"))
repo.all().forEach(::printPerson)
Delegates.vetoable(0) { // it's an inline function
kprop, oldValue, newValue ->
newValue in 0..122 // Jeanne Calmen
}
val ageDelegate = {
Delegates.vetoable(0) {
kprop, oldValue, newValue ->
newValue in 0..122
}
}
if you don't use it as a function, it will return
the last value for the new instance
val ageDelegate = {
Delegates.vetoable(0) {
kprop, oldValue, newValue ->
newValue in 0..122
}
}
class Person(val id: String, val name: String) {
var age: Int by ageDelegate()
}
val ageDelegate = {
Delegates.vetoable(0) {
kprop, oldValue, newValue ->
newValue in 0..122
}
}
class Person(val id: String, val name: String) {
var age: Int by ageDelegate()
}
val p = Person("3", "Nelson")
p.age = -1
printPerson(p)
p.age = 150
printPerson(p)
p.age = 35
printPerson(p)
	3	-	Nelson	-	0	
	3	-	Nelson	-	0	
		
	3	-	Nelson	-	35
interface OnFilterCallback {
fun onFilterChanged(f: Filter)
}
class Filter {
var minBathNum: Int = 0
var minPrice: Float = 0f
private val callbacks = mutableSetOf<OnFilterCallback>()
fun addOnFilterChangedCallback(callback: OnFilterCallback) {
callbacks += callback
}
}
class Filter {
var minBathNum: Int = 0
var minPrice: Float = 0f
private val callbacks = mutableSetOf<OnFilterCallback>()
fun addOnFilterChangedCallback(callback: OnFilterCallback) {
callbacks += callback
}
fun notifyObservers() {
callbacks.forEach{ it.onFilterChanged(this) }
}
}
class FilterDelegate<T>(initial: T) {
var internal: T = initial
operator fun getValue(thisRef: Filter, prop: KProperty<*>): T {
return internal
}
operator fun setValue(thisRef: Filter, prop: KProperty<*>, value: T) {
internal = value
thisRef.notifyObservers()
}
}
interface OnFilterCallback {
fun onFilterChanged(f: Filter)
}
class Filter {
var minBathNum: Int by FilterDelegate(0)
var minPrice: Float by FilterDelegate(0f)
private val callbacks = mutableSetOf<OnFilterCallback>()
fun addOnFilterChangedCallback(callback: OnFilterCallback) {
callbacks += callback
}
fun notifyObservers() {
callbacks.forEach{ it.onFilterChanged(this) }
}
}
val filter = Filter()
filter.addOnFilterChangedCallback(object: OnFilterCallback {
override fun onFilterChanged(f: Filter) {
println("Observer #1")
println("MinPrice: ${f.minPrice} - Baths:${f.minBathNum}")
}
})
filter.addOnFilterChangedCallback(object : OnFilterCallback {
override fun onFilterChanged(f: Filter) {
println("Observer #2")
println("MinPrice: ${f.minPrice} - Baths:${f.minBathNum}")
}
})
filter.minBathNum = 2
filter.minPrice = 100_000f
filter.minBathNum = 1
filter.minPrice = 10f
Observer	#1	|	MinPrice:	0.0	-	Baths:2	
Observer	#2	|	MinPrice:	0.0	-	Baths:2	
Observer	#1	|	MinPrice:	100000.0	-	Baths:2	
Observer	#2	|	MinPrice:	100000.0	-	Baths:2	
Observer	#1	|	MinPrice:	100000.0	-	Baths:1	
Observer	#2	|	MinPrice:	100000.0	-	Baths:1	
Observer	#1	|	MinPrice:	10.0	-	Baths:1	
Observer	#2	|	MinPrice:	10.0	-	Baths:1
fun <T> Filter.filterDelegate(initialValue: T) =
Delegates.observable(initialValue) { prop, oldValue, newValue ->
println("old: $oldValue -> new: $newValue")
this.notifyObservers()
}
fun <T> Filter.filterDelegate(initialValue: T) =
Delegates.observable(initialValue) { prop, oldValue, newValue ->
println("old: $oldValue -> new: $newValue")
this.notifyObservers()
}
class Filter {
var minBathNum: Int by filterDelegate(0)
var minPrice: Float by filterDelegate(0f)
...
}
val filter = Filter()
filter.addOnFilterChangedCallback(object: OnFilterCallback {
override fun onFilterChanged(f: Filter) {
println("Observer #1”)
}
})
filter.addOnFilterChangedCallback(object : OnFilterCallback {
override fun onFilterChanged(f: Filter) {
println("Observer #2")
}
})
filter.minBathNum = 2
filter.minPrice = 100_000f
filter.minBathNum = 1
filter.minPrice = 10f
old:	0	->	new:	2	
Observer	#1	
Observer	#2	
old:	0.0	->	new:	100000.0	
Observer	#1	
Observer	#2	
old:	2	->	new:	1	
Observer	#1	
Observer	#2	
old:	100000.0	->	new:	10.0	
Observer	#1	
Observer	#2
• Interface delegation for composition.
• lazy for… lazy initialization.
• vetoable to define a validation to be reused.
• observable if you need both old and new value.
• Custom delegates for everything else.
Delegates - Summary
• Std Lib has a lot of functions to help you to write a more
simple, readable and concise code.
• Check it out the lib internals. You’ll learn a lot!
• Check it out the Kotlin Koans (https://play.kotlinlang.org/
koans). It’s a good place to start (or recap)!
• Write Kotlin code, enjoy the std lib and have fun! 😉
Wrap up!
• Kotlin Standard Functions

https://medium.com/androiddevelopers/kotlin-standard-functions-
cheat-sheet-27f032dd4326
• Mastering Kotlin standard functions: run, with, let, also and apply

https://medium.com/@elye.project/mastering-kotlin-standard-
functions-run-with-let-also-and-apply-9cd334b0ef84
• Java Friendly Kotlin

https://codelabs.developers.google.com/codelabs/java-friendly-kotlin
• Simpler Kotlin class hierarchies using class delegation

https://proandroiddev.com/simpler-kotlin-class-hierarchies-using-
class-delegation-35464106fed5
References
Gracias!
Nelson Glauber
@nglauber
Ad

More Related Content

What's hot (20)

Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
intelliyole
 
OneRing @ OSCamp 2010
OneRing @ OSCamp 2010OneRing @ OSCamp 2010
OneRing @ OSCamp 2010
Qiangning Hong
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
intelliyole
 
ES6 Overview
ES6 OverviewES6 Overview
ES6 Overview
Bruno Scopelliti
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
Luke Donnet
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
Chandra Sekhar Nayak
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
Kirill Rozov
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
Brendan Eich
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
ES6 in Real Life
ES6 in Real LifeES6 in Real Life
ES6 in Real Life
Domenic Denicola
 
Comparing JVM languages
Comparing JVM languagesComparing JVM languages
Comparing JVM languages
Jose Manuel Ortega Candel
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
NAVER Engineering
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
hesher
 
Kotlin: a better Java
Kotlin: a better JavaKotlin: a better Java
Kotlin: a better Java
Nils Breunese
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
Jung Kim
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
Andrey Breslav
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
intelliyole
 
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)Feel of Kotlin (Berlin JUG 16 Apr 2015)
Feel of Kotlin (Berlin JUG 16 Apr 2015)
intelliyole
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
Luke Donnet
 
Kotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is comingKotlin Coroutines. Flow is coming
Kotlin Coroutines. Flow is coming
Kirill Rozov
 
Proxies are Awesome!
Proxies are Awesome!Proxies are Awesome!
Proxies are Awesome!
Brendan Eich
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Dmitry Soshnikov
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Domenic Denicola
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
NAVER Engineering
 
ES2015 (ES6) Overview
ES2015 (ES6) OverviewES2015 (ES6) Overview
ES2015 (ES6) Overview
hesher
 
Kotlin: a better Java
Kotlin: a better JavaKotlin: a better Java
Kotlin: a better Java
Nils Breunese
 
Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2Intro to Reactive Thinking and RxJava 2
Intro to Reactive Thinking and RxJava 2
JollyRogers5
 
Letswift19-clean-architecture
Letswift19-clean-architectureLetswift19-clean-architecture
Letswift19-clean-architecture
Jung Kim
 
EcmaScript 6 - The future is here
EcmaScript 6 - The future is hereEcmaScript 6 - The future is here
EcmaScript 6 - The future is here
Sebastiano Armeli
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
Adam L Barrett
 
JVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in KotlinJVMLS 2016. Coroutines in Kotlin
JVMLS 2016. Coroutines in Kotlin
Andrey Breslav
 

Similar to Mastering Kotlin Standard Library (20)

The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196
Mahmoud Samir Fayed
 
[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8
Alonso Torres
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
C++ theory
C++ theoryC++ theory
C++ theory
Shyam Khant
 
KotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptxKotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptx
Ian Robertson
 
Java session4
Java session4Java session4
Java session4
Jigarthacker
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
James Titcumb
 
Wien15 java8
Wien15 java8Wien15 java8
Wien15 java8
Jaanus Pöial
 
Java Generics
Java GenericsJava Generics
Java Generics
jeslie
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
Muthu Vinayagam
 
Intro to Kotlin
Intro to KotlinIntro to Kotlin
Intro to Kotlin
Magda Miu
 
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Tudor Dragan
 
Ruby Programming Assignment Help
Ruby Programming Assignment HelpRuby Programming Assignment Help
Ruby Programming Assignment Help
HelpWithAssignment.com
 
Ruby Programming Assignment Help
Ruby Programming Assignment HelpRuby Programming Assignment Help
Ruby Programming Assignment Help
HelpWithAssignment.com
 
SeaJUG March 2004 - Groovy
SeaJUG March 2004 - GroovySeaJUG March 2004 - Groovy
SeaJUG March 2004 - Groovy
Ted Leung
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
Akaks
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - Javaz
Alexey Remnev
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Сбертех | SberTech
 
Twig tips and tricks
Twig tips and tricksTwig tips and tricks
Twig tips and tricks
Javier Eguiluz
 
The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196The Ring programming language version 1.7 book - Part 35 of 196
The Ring programming language version 1.7 book - Part 35 of 196
Mahmoud Samir Fayed
 
[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8[Codemotion 2015] patrones de diseño con java8
[Codemotion 2015] patrones de diseño con java8
Alonso Torres
 
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kotlin Advanced - Apalon Kotlin Sprint Part 3
Kirill Rozov
 
FP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyondFP in Java - Project Lambda and beyond
FP in Java - Project Lambda and beyond
Mario Fusco
 
KotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptxKotlinForJavaDevelopers-UJUG.pptx
KotlinForJavaDevelopers-UJUG.pptx
Ian Robertson
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
James Titcumb
 
Java Generics
Java GenericsJava Generics
Java Generics
jeslie
 
GE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python ProgrammingGE8151 Problem Solving and Python Programming
GE8151 Problem Solving and Python Programming
Muthu Vinayagam
 
Intro to Kotlin
Intro to KotlinIntro to Kotlin
Intro to Kotlin
Magda Miu
 
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Kotlin - The Swiss army knife of programming languages - Visma Mobile Meet-up...
Tudor Dragan
 
SeaJUG March 2004 - Groovy
SeaJUG March 2004 - GroovySeaJUG March 2004 - Groovy
SeaJUG March 2004 - Groovy
Ted Leung
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
Akaks
 
Thumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - JavazThumbtack Expertise Days # 5 - Javaz
Thumbtack Expertise Days # 5 - Javaz
Alexey Remnev
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Сбертех | SberTech
 
Ad

More from Nelson Glauber Leal (20)

Insights no desenvolvimento Android para 2024
Insights no desenvolvimento Android para 2024Insights no desenvolvimento Android para 2024
Insights no desenvolvimento Android para 2024
Nelson Glauber Leal
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023
Nelson Glauber Leal
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
Nelson Glauber Leal
 
Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)
Nelson Glauber Leal
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
Nelson Glauber Leal
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
Nelson Glauber Leal
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
Nelson Glauber Leal
 
O que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor AndroidO que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor Android
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
Nelson Glauber Leal
 
Introdução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com KotlinIntrodução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com Kotlin
Nelson Glauber Leal
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos AndroidDesenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos Android
Nelson Glauber Leal
 
Desenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos AndroidDesenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos Android
Nelson Glauber Leal
 
Turbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinTurbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com Kotlin
Nelson Glauber Leal
 
Tudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint LayoutTudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint Layout
Nelson Glauber Leal
 
Persistência de Dados no SQLite com Room
Persistência de Dados no SQLite com RoomPersistência de Dados no SQLite com Room
Persistência de Dados no SQLite com Room
Nelson Glauber Leal
 
The world of Android Animations
The world of Android AnimationsThe world of Android Animations
The world of Android Animations
Nelson Glauber Leal
 
Insights no desenvolvimento Android para 2024
Insights no desenvolvimento Android para 2024Insights no desenvolvimento Android para 2024
Insights no desenvolvimento Android para 2024
Nelson Glauber Leal
 
Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023
Nelson Glauber Leal
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
Nelson Glauber Leal
 
Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)
Nelson Glauber Leal
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
Nelson Glauber Leal
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
Nelson Glauber Leal
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
Nelson Glauber Leal
 
O que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor AndroidO que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor Android
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
Nelson Glauber Leal
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
Nelson Glauber Leal
 
Introdução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com KotlinIntrodução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com Kotlin
Nelson Glauber Leal
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
Nelson Glauber Leal
 
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos AndroidDesenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos Android
Nelson Glauber Leal
 
Desenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos AndroidDesenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos Android
Nelson Glauber Leal
 
Turbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinTurbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com Kotlin
Nelson Glauber Leal
 
Tudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint LayoutTudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint Layout
Nelson Glauber Leal
 
Persistência de Dados no SQLite com Room
Persistência de Dados no SQLite com RoomPersistência de Dados no SQLite com Room
Persistência de Dados no SQLite com Room
Nelson Glauber Leal
 
Ad

Recently uploaded (20)

PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
saimabibi60507
 
Implementing promises with typescripts, step by step
Implementing promises with typescripts, step by stepImplementing promises with typescripts, step by step
Implementing promises with typescripts, step by step
Ran Wahle
 
Top 10 Data Cleansing Tools for 2025.pdf
Top 10 Data Cleansing Tools for 2025.pdfTop 10 Data Cleansing Tools for 2025.pdf
Top 10 Data Cleansing Tools for 2025.pdf
AffinityCore
 
Societal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainabilitySocietal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainability
Jordi Cabot
 
Landscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature ReviewLandscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature Review
Hironori Washizaki
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Cryptocurrency Exchange Script like Binance.pptx
Cryptocurrency Exchange Script like Binance.pptxCryptocurrency Exchange Script like Binance.pptx
Cryptocurrency Exchange Script like Binance.pptx
riyageorge2024
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
Lionel Briand
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdfMicrosoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
TechSoup
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
DVDFab Crack FREE Download Latest Version 2025
DVDFab Crack FREE Download Latest Version 2025DVDFab Crack FREE Download Latest Version 2025
DVDFab Crack FREE Download Latest Version 2025
younisnoman75
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Foundation Models for Time Series : A Survey
Foundation Models for Time Series : A SurveyFoundation Models for Time Series : A Survey
Foundation Models for Time Series : A Survey
jayanthkalyanam1
 
Not So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java WebinarNot So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java Webinar
Tier1 app
 
PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
PRTG Network Monitor Crack Latest Version & Serial Key 2025 [100% Working]
saimabibi60507
 
Implementing promises with typescripts, step by step
Implementing promises with typescripts, step by stepImplementing promises with typescripts, step by step
Implementing promises with typescripts, step by step
Ran Wahle
 
Top 10 Data Cleansing Tools for 2025.pdf
Top 10 Data Cleansing Tools for 2025.pdfTop 10 Data Cleansing Tools for 2025.pdf
Top 10 Data Cleansing Tools for 2025.pdf
AffinityCore
 
Societal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainabilitySocietal challenges of AI: biases, multilinguism and sustainability
Societal challenges of AI: biases, multilinguism and sustainability
Jordi Cabot
 
Landscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature ReviewLandscape of Requirements Engineering for/by AI through Literature Review
Landscape of Requirements Engineering for/by AI through Literature Review
Hironori Washizaki
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
F-Secure Freedome VPN 2025 Crack Plus Activation  New VersionF-Secure Freedome VPN 2025 Crack Plus Activation  New Version
F-Secure Freedome VPN 2025 Crack Plus Activation New Version
saimabibi60507
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Cryptocurrency Exchange Script like Binance.pptx
Cryptocurrency Exchange Script like Binance.pptxCryptocurrency Exchange Script like Binance.pptx
Cryptocurrency Exchange Script like Binance.pptx
riyageorge2024
 
Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)Who Watches the Watchmen (SciFiDevCon 2025)
Who Watches the Watchmen (SciFiDevCon 2025)
Allon Mureinik
 
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
TestMigrationsInPy: A Dataset of Test Migrations from Unittest to Pytest (MSR...
Andre Hora
 
Download YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full ActivatedDownload YouTube By Click 2025 Free Full Activated
Download YouTube By Click 2025 Free Full Activated
saniamalik72555
 
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
FlakyFix: Using Large Language Models for Predicting Flaky Test Fix Categorie...
Lionel Briand
 
Exploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the FutureExploring Wayland: A Modern Display Server for the Future
Exploring Wayland: A Modern Display Server for the Future
ICS
 
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdfMicrosoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
Microsoft AI Nonprofit Use Cases and Live Demo_2025.04.30.pdf
TechSoup
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
DVDFab Crack FREE Download Latest Version 2025
DVDFab Crack FREE Download Latest Version 2025DVDFab Crack FREE Download Latest Version 2025
DVDFab Crack FREE Download Latest Version 2025
younisnoman75
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Foundation Models for Time Series : A Survey
Foundation Models for Time Series : A SurveyFoundation Models for Time Series : A Survey
Foundation Models for Time Series : A Survey
jayanthkalyanam1
 
Not So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java WebinarNot So Common Memory Leaks in Java Webinar
Not So Common Memory Leaks in Java Webinar
Tier1 app
 

Mastering Kotlin Standard Library

  • 2. • Provides the essential types, classes and functions for everyday work with Kotlin. • In version 1.3 it contains approximately 50 sub packages organized in 4 categories: 
 Common, JVM, JS and Native. Kotlin Std Lib
  • 3. • Provides the essential types, classes and functions for everyday work with Kotlin. • In version 1.3 it contains approximately 50 sub packages organized in 4 categories: 
 Common, JVM, JS and Native. Kotlin Std Lib
  • 5. • T.let { } • T.apply { } • T.also { } • T.run { } • run { } • with(T) { } Scope Functions
  • 6. • It’s an extension function. • Caller is represented by it. • Returns the block’s last line. • It’s commonly used for nullability checking. public inline fun <T, R> T.let(block: (T) -> R): R { return block(this) }
  • 7. fun deleteTempPhoto() { var tempImageFile: File? = // ... tempImageFile?.let { if (it.exists()) it.delete() } }
  • 8. fun deleteTempPhoto() { var tempImageFile: File? = // ... if (tempImageFile != null) { if (tempImageFile.exists()) // thanks smart cast! tempImageFile.delete() } }
  • 9. class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { if (tempImageFile != null && tempImageFile.exists()) tempImageFile.delete() } }
  • 10. class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { if (tempImageFile != null && tempImageFile.exists()) tempImageFile.delete() } }
  • 11. Smart cast to 'File' is impossible, because 'tempImageFile' is a mutable property that could have been changed by this time class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { if (tempImageFile != null && tempImageFile.exists()) tempImageFile.delete() } }
  • 12. class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { if (tempImageFile != null && tempImageFile?.exists() == true ) tempImageFile?.delete() } } 😒😱
  • 13. class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { tempImageFile?.let { if (it.exists()) it.delete() } } }
  • 14. class SomeClass { var tempImageFile: File? = null fun deleteTempPhoto() { tempImageFile?.let { file -> if (file.exists()) file.delete() } } } 😎
  • 15. • It’s an extension function. • Caller is represented by this. • Returns the caller itself (this). • It’s commonly used for initializing and configuring an object. public inline fun <T> T.apply(block: T.() -> Unit): T { block() return this }
  • 16. val chip = Chip(this) chip.text = weatherType.name.capitalize() chip.setChipBackgroundColorResource(R.color.colorAccent) chip.isClickable = false chip.isCheckable = false chip.isCloseIconVisible = true chip.setOnCloseIconClickListener { if (viewModel.unselectWeatherType(weatherType)) { chipGroup.removeView(it) } } chipGroup.addView(chip)
  • 17. val chip = Chip(this) chip.text = weatherType.name.capitalize() chip.setChipBackgroundColorResource(R.color.colorAccent) chip.isClickable = false chip.isCheckable = false chip.isCloseIconVisible = true chip.setOnCloseIconClickListener { if (viewModel.unselectWeatherType(weatherType)) { chipGroup.removeView(it) } } chipGroup.addView(chip)
  • 18. val chip = Chip(this).apply { text = weatherType.name.capitalize() setChipBackgroundColorResource(R.color.colorAccent) isClickable = false isCheckable = false isCloseIconVisible = true setOnCloseIconClickListener { if (viewModel.unselectWeatherType(weatherType)) { chipGroup.removeView(it) } } } chipGroup.addView(chip)
  • 19. • It’s an extension function. • Caller is represented by it. • Returns the caller itself (this). • It’s commonly used for chaining object initialization or simple to separate one action from another. public inline fun <T> T.also(block: (T) -> Unit): T { block(this) return this }
  • 20. val chip = Chip(this).apply { text = weatherType.name.capitalize() setChipBackgroundColorResource(R.color.colorAccent) isClickable = false isCheckable = false isCloseIconVisible = true setOnCloseIconClickListener { if (viewModel.unselectWeatherType(weatherType)) { chipGroup.removeView(it) } } } chipGroup.addView(chip)
  • 21. Chip(this).apply { text = weatherType.name.capitalize() setChipBackgroundColorResource(R.color.colorAccent) isClickable = false isCheckable = false isCloseIconVisible = true setOnCloseIconClickListener { if (viewModel.unselectWeatherType(weatherType)) { chipGroup.removeView(it) } } }.also { chipGroup.addView(it) }
  • 22. • It’s an extension function. • Caller is represented by this. • Returns the block’s last line. • It’s commonly used to get the result of an operation using an object. public inline fun <T, R> T.run(block: T.() -> R): R { return block() }
  • 23. public inline fun <R> run(block: () -> R): R { return block() } • It’s not an extension function. • There’s no reference to the caller (once it’s not an extension function). • Returns the block’s last line. • It’s commonly used to get the result of an operation.
  • 24. private fun getFavoriteCity(): String { val prefs = PreferenceManager.getDefaultSharedPreferences(this) return prefs.getString("favCity", null) ?: getString(R.string.pref_city_default) }
  • 25. private fun getFavoriteCity() = PreferenceManager.getDefaultSharedPreferences(this).run { getString("favCity", null) } ?: run { getString(R.string.pref_city_default) }
  • 26. • It’s not an extension function. • The caller is passed as parameter and is referenced by this. • Returns the block’s last line. • It’s commonly used when you want to remember Delphi. public inline fun <T, R> with(receiver: T, block: T.() -> R): R { return receiver.block() }
  • 27. val webView: WebView = loadWebView() with(webView) { settings.javaScriptEnabled = true loadUrl("file:///android_asset/app_page.html") }
  • 28. val webView: WebView? = loadWebView() with(webView) { settings.javaScriptEnabled = true loadUrl("file:///android_asset/app_page.html") }
  • 29. val webView: WebView? = loadWebView() with(webView) { settings.javaScriptEnabled = true loadUrl("file:///android_asset/app_page.html") } Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type WebView?
  • 30. val webView: WebView? = loadWebView() with(webView) { this?.settings?.javaScriptEnabled = true this?.loadUrl("file:///android_asset/app_page.html") } 😩
  • 31. val webView: WebView? = loadWebView() webView?.let { it.settings.javaScriptEnabled = true it.loadUrl("file:///android_asset/app_page.html") } %
  • 32. • T.let { } for nullability check. • T.apply { } for object initialization. • T.also { } for initialization chaining or a simple change of scope. • T.run { } to get a result from an object sequence of calls. • run { } to get a result from a sequence of calls. • with(T) { } for some reason you don’t know how to explain… :) Scope Functions - Summary
  • 35. fun sayHello() { println("Hello!") } fun greetings(message: String = "Hello") { println(message) }
  • 36. @Deprecated( message = "This function is being replaced.", replaceWith = ReplaceWith("greetings(message)"), level = DeprecationLevel.WARNING) fun sayHello() { println("Hello!") } fun greetings(message: String = "Hello") { println(message) }
  • 37. @Deprecated( message = "This function is being replaced.", replaceWith = ReplaceWith("greetings(message)"), level = DeprecationLevel.WARNING) fun sayHello() { println("Hello!") } fun greetings(message: String = "Hello") { println(message) } fun main() { sayHello() }
  • 38. fun login(userName: String, password: String) { // Do login }
  • 39. fun login(userName: String, password: String) { // Do login } data class AuthUser(val name: String, val password: String) fun login(authUser: AuthUser) { // New login with user }
  • 40. fun login(userName: String, password: String) { // Do login } @Experimental(Experimental.Level.WARNING) annotation class NewApi data class AuthUser(val name: String, val password: String) fun login(authUser: AuthUser) { // New login with user }
  • 41. fun login(userName: String, password: String) { // Do login } @Experimental(Experimental.Level.WARNING) annotation class NewApi @NewApi data class AuthUser(val name: String, val password: String) @NewApi fun login(authUser: AuthUser) { // New login with user }
  • 42. fun login(userName: String, password: String) { // Do login } @Experimental(Experimental.Level.WARNING) annotation class NewApi @NewApi data class AuthUser(val name: String, val password: String) @NewApi fun login(authUser: AuthUser) { // New login with user } @UseExperimental(NewApi::class) fun main() { login(AuthUser("ngvl", "123")) }
  • 43. • JvmStatic • JvmOverloads • JvmName • JvmField • Throws @Jvm* annotations
  • 44. object UserRepository { fun insertUser(user: User) { // insert user } }
  • 45. object UserRepository { fun insertUser(user: User) { // insert user } } public class MyJavaClass { ... public void addUser() { UserRepository.INSTANCE.insertUser(new User("Nelson")); } }
  • 46. object UserRepository { @JvmStatic fun insertUser(user: User) { // insert user } } public class MyJavaClass { ... public void addUser() { UserRepository.INSTANCE.insertUser(new User("Nelson")); } }
  • 47. object UserRepository { @JvmStatic fun insertUser(user: User) { // insert user } } public class MyJavaClass { ... public void addUser() { UserRepository.insertUser(new User("Nelson")); } }
  • 48. class MyKotlinClass { fun printName(name: String = "Anonymous") { println("Hello $name!") } //... }
  • 49. class MyKotlinClass { fun printName(name: String = "Anonymous") { println("Hello $name!") } //... } MyKotlinClass instance = new MyKotlinClass(); instance.printName("Nelson"); // Works! instance.printName(); // Error!
  • 50. class MyKotlinClass { @JvmOverloads fun printName(name: String = "Anonymous") { println("Hello $name!") } //... }
  • 51. class MyKotlinClass { @JvmOverloads fun printName(name: String = "Anonymous") { println("Hello $name!") } //... } MyKotlinClass instance = new MyKotlinClass(); instance.printName("Nelson"); instance.printName();
  • 52. public class MyCustomView extends LinearLayout { public MyCustomView(Context context) { super(context); } public MyCustomView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyCustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } ... }
  • 53. class MyCustomView : LinearLayout { constructor(context: Context) : super(context) { } constructor(context: Context, attrs: AttributeSet? ) : super(context, attrs) { } constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int ) : super(context, attrs, defStyleAttr) { }
  • 54. class MyCustomView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr) { ... }
  • 55. class ToggleView { private var onOff = false fun switch() { onOff = !onOff } } ToggleView toggleView = new ToggleView(); toggleView.switch(); // error!
  • 56. class ToggleView { private var onOff = false @JvmName("switchOnOff") fun switch() { onOff = !onOff } } ToggleView toggleView = new ToggleView(); toggleView.switchOnOff();
  • 57. // StringsExtensions.kt package ngvl.kotlin.demo.string fun String.shouldCapitalizeName() = this !in listOf("da", "das", "de", "di", "do", "dos") fun String.capitalizeName() = this.split(" ") .joinToString(" ") { if (it.shouldCapitalizeName()) it.capitalize() else it } // Some Java file... String name = StringExtensionsKt.capitalizeName("nelson glauber");
  • 58. // StringsExtensions.kt @file:JvmName("StringExt") package ngvl.kotlin.demo.string fun String.shouldCapitalizeName() = this !in listOf("da", "das", "de", "di", "do", "dos") fun String.capitalizeName() = this.split(" ") .joinToString(" ") { if (it.shouldCapitalizeName()) it.capitalize() else it } // Some Java file... String name = StringExtensionsKt.capitalizeName("nelson glauber");
  • 59. // StringsExtensions.kt @file:JvmName("StringExt") package ngvl.kotlin.demo.string fun String.shouldCapitalizeName() = this !in listOf("da", "das", "de", "di", "do", "dos") fun String.capitalizeName() = this.split(" ") .joinToString(" ") { if (it.shouldCapitalizeName()) it.capitalize() else it } // Some Java file... String name = StringExt.capitalizeName("nelson glauber");
  • 60. data class Product( val id: String, val description: String, val price: Float = 0f ) Product product = new Product("001", "Smartphone", 0f); System.out.println( product.getId() +" - "+ product.getDescription() +" = "+ product.getPrice() );
  • 61. Product product = new Product("001", "Smartphone", 0f); System.out.println( product.getId() +" - "+ product.getDescription() +" = "+ product.getPrice() ); data class Product( @JvmField val id: String, @JvmField val description: String, @JvmField val price: Float = 0f )
  • 62. data class Product( @JvmField val id: String, @JvmField val description: String, @JvmField val price: Float = 0f ) Product product = new Product("001", "Smartphone", 0f); System.out.println( product.id +" - "+ product.description +" = "+ product.price );
  • 63. class MyKotlinClass { companion object { val CONSTANT_1 = 1 const val CONSTANT_2 = 2 @JvmField val CONSTANT_3 = 3 @JvmField val ROOT = User("root") } } MyKotlinClass.Companion.getCONSTANT_1(); MyKotlinClass.CONSTANT_2; MyKotlinClass.CONSTANT_3; MyKotlinClass.ROOT;
  • 64. object UserRepository { @JvmStatic fun insertUser(user: User) { if (user.name.length < 5) throw NameTooShortException() // insert user ... } } UserRepository.insertUser(new User("ngvl"));
  • 65. object UserRepository { @JvmStatic @Throws(NameTooShortException::class) fun insertUser(user: User) { if (user.name.length < 5) { throw NameTooShortException() } // insert user ... } } UserRepository.insertUser(new User("ngvl"));
  • 66. try { UserRepository.insertUser(new User("ngvl")); } catch (NameTooShortException e) { // handle name too short } object UserRepository { @JvmStatic @Throws(NameTooShortException::class) fun insertUser(user: User) { if (user.name.length < 5) { throw NameTooShortException() } // insert user ... } }
  • 67. data class Recipe( var name: String? = null, var ingredients: List<Ingredient> = mutableListOf() ) data class Ingredient( var description: String? = null, var quantity: Int = 0, var unity: String? = null )
  • 68. data class Recipe( var name: String? = null, var ingredients: List<Ingredient> = mutableListOf() ) data class Ingredient( var description: String? = null, var quantity: Int = 0, var unity: String? = null ) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) } public inline fun <T> T.apply(block: T.() -> Unit): T { block() return this }
  • 69. fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) } val recipe = recipe { name = "Chocolate Cake" ingredient { name = "Flour" quantity = 3 unity = "cups" } } println(recipe) Recipe(name=Flour, ingredients=[ Ingredient(description=null, quantity=3, unity=cups)] ) 🤔
  • 70. data class Recipe( var name: String? = null, var ingredients: List<Ingredient> = mutableListOf() ) data class Ingredient( var description: String? = null, var quantity: Int = 0, var unity: String? = null ) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) }
  • 71. @DslMarker annotation class RecipeLang @RecipeLang data class Recipe( var name: String? = null, var ingredients: List<Ingredient> = mutableListOf() ) @RecipeLang data class Ingredient( var description: String? = null, var quantity: Int = 0, var unity: String? = null ) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) }
  • 72. val recipe = recipe { name = "Chocolate Cake" ingredient { name = "Flour" quantity = 3 unity = "cups" } } println(recipe) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) } Compile error: 'var name: String?' can't be called in this context by implicit receiver. Use the explicit one if necessary
  • 73. val recipe = recipe { name = "Chocolate Cake" ingredient { [email protected] = "Choc.Cake" quantity = 3 unity = "cups" } } println(recipe) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) }
  • 74. val recipe = recipe { name = "Chocolate Cake" ingredient { description = "Flour" quantity = 3 unity = "cups" } } println(recipe) fun recipe(build: Recipe.() -> Unit) = Recipe().apply(build) fun Recipe.ingredient(build: Ingredient.() -> Unit) { ingredients += Ingredient().apply(build) } Recipe(name=Chocolate Cake, ingredients=[ Ingredient(description=Flour, quantity=3, unity=cups)] ) 😋
  • 75. • @Deprecated and @Experimental help to document the evolution of your code • @Jvm* annotations help the integration with Java code. • @DslMarker create scopes for your DSLs. Annotations - Summary
  • 77. abstract class Individual( val name: String, val surname: String, val age: Int ) class Student( name: String, surname: String, age: Int, val university: String ) : Individual(name, surname, age) class Worker( name: String, surname: String, age: Int, val company: String ) : Individual(name, surname, age)
  • 78. abstract class Individual( val name: String, val surname: String, val age: Int ) class Student( name: String, surname: String, age: Int, val university: String ) : Individual(name, surname, age) class Worker( name: String, surname: String, age: Int, val company: String ) : Individual(name, surname, age)
  • 79. interface Individual { val name: String val surname: String val age: Int } data class IndividualData( override val name: String, override val surname: String, override val age: Int ) : Individual data class Student( val data: IndividualData, val university: String ) : Individual by data data class Worker( val data: IndividualData, val company: String ) : Individual by data
  • 80. interface Individual { val name: String val surname: String val age: Int } data class IndividualData( override val name: String, override val surname: String, override val age: Int ) : Individual data class Student( val data: IndividualData, val university: String ) : Individual by data data class Worker( val data: IndividualData, val company: String ) : Individual by data val student = Student( IndividualData("Nelson", "Leal", 36), "Universo" ) student.run { println("$name $surname - $age - $university") } Nelson Leal - 36 - Universo
  • 81. class Repository { private val peopleDAO: PeopleDAO by lazy { Database.getPeopleDAO() } fun insert(person: Person) { peopleDAO.add(person) } fun all(): List<Person> = peopleDAO.list() }
  • 82. class Repository { private val peopleDAO: PeopleDAO by lazy { Database.getPeopleDAO() } fun insert(person: Person) { peopleDAO.add(person) } fun all(): List<Person> = peopleDAO.list() }
  • 83. class Repository { private val peopleDAO: PeopleDAO by lazy { Database.getPeopleDAO() } fun insert(person: Person) { peopleDAO.add(person) } fun all(): List<Person> = peopleDAO.list() } val repo = Repository() repo.insert(Person("1", "Nelson")) repo.insert(Person("2", "Glauber")) repo.all().forEach(::printPerson)
  • 84. Delegates.vetoable(0) { // it's an inline function kprop, oldValue, newValue -> newValue in 0..122 // Jeanne Calmen }
  • 85. val ageDelegate = { Delegates.vetoable(0) { kprop, oldValue, newValue -> newValue in 0..122 } } if you don't use it as a function, it will return the last value for the new instance
  • 86. val ageDelegate = { Delegates.vetoable(0) { kprop, oldValue, newValue -> newValue in 0..122 } } class Person(val id: String, val name: String) { var age: Int by ageDelegate() }
  • 87. val ageDelegate = { Delegates.vetoable(0) { kprop, oldValue, newValue -> newValue in 0..122 } } class Person(val id: String, val name: String) { var age: Int by ageDelegate() } val p = Person("3", "Nelson") p.age = -1 printPerson(p) p.age = 150 printPerson(p) p.age = 35 printPerson(p) 3 - Nelson - 0 3 - Nelson - 0 3 - Nelson - 35
  • 88. interface OnFilterCallback { fun onFilterChanged(f: Filter) } class Filter { var minBathNum: Int = 0 var minPrice: Float = 0f private val callbacks = mutableSetOf<OnFilterCallback>() fun addOnFilterChangedCallback(callback: OnFilterCallback) { callbacks += callback } }
  • 89. class Filter { var minBathNum: Int = 0 var minPrice: Float = 0f private val callbacks = mutableSetOf<OnFilterCallback>() fun addOnFilterChangedCallback(callback: OnFilterCallback) { callbacks += callback } fun notifyObservers() { callbacks.forEach{ it.onFilterChanged(this) } } }
  • 90. class FilterDelegate<T>(initial: T) { var internal: T = initial operator fun getValue(thisRef: Filter, prop: KProperty<*>): T { return internal } operator fun setValue(thisRef: Filter, prop: KProperty<*>, value: T) { internal = value thisRef.notifyObservers() } }
  • 91. interface OnFilterCallback { fun onFilterChanged(f: Filter) } class Filter { var minBathNum: Int by FilterDelegate(0) var minPrice: Float by FilterDelegate(0f) private val callbacks = mutableSetOf<OnFilterCallback>() fun addOnFilterChangedCallback(callback: OnFilterCallback) { callbacks += callback } fun notifyObservers() { callbacks.forEach{ it.onFilterChanged(this) } } }
  • 92. val filter = Filter() filter.addOnFilterChangedCallback(object: OnFilterCallback { override fun onFilterChanged(f: Filter) { println("Observer #1") println("MinPrice: ${f.minPrice} - Baths:${f.minBathNum}") } }) filter.addOnFilterChangedCallback(object : OnFilterCallback { override fun onFilterChanged(f: Filter) { println("Observer #2") println("MinPrice: ${f.minPrice} - Baths:${f.minBathNum}") } }) filter.minBathNum = 2 filter.minPrice = 100_000f filter.minBathNum = 1 filter.minPrice = 10f Observer #1 | MinPrice: 0.0 - Baths:2 Observer #2 | MinPrice: 0.0 - Baths:2 Observer #1 | MinPrice: 100000.0 - Baths:2 Observer #2 | MinPrice: 100000.0 - Baths:2 Observer #1 | MinPrice: 100000.0 - Baths:1 Observer #2 | MinPrice: 100000.0 - Baths:1 Observer #1 | MinPrice: 10.0 - Baths:1 Observer #2 | MinPrice: 10.0 - Baths:1
  • 93. fun <T> Filter.filterDelegate(initialValue: T) = Delegates.observable(initialValue) { prop, oldValue, newValue -> println("old: $oldValue -> new: $newValue") this.notifyObservers() }
  • 94. fun <T> Filter.filterDelegate(initialValue: T) = Delegates.observable(initialValue) { prop, oldValue, newValue -> println("old: $oldValue -> new: $newValue") this.notifyObservers() } class Filter { var minBathNum: Int by filterDelegate(0) var minPrice: Float by filterDelegate(0f) ... }
  • 95. val filter = Filter() filter.addOnFilterChangedCallback(object: OnFilterCallback { override fun onFilterChanged(f: Filter) { println("Observer #1”) } }) filter.addOnFilterChangedCallback(object : OnFilterCallback { override fun onFilterChanged(f: Filter) { println("Observer #2") } }) filter.minBathNum = 2 filter.minPrice = 100_000f filter.minBathNum = 1 filter.minPrice = 10f old: 0 -> new: 2 Observer #1 Observer #2 old: 0.0 -> new: 100000.0 Observer #1 Observer #2 old: 2 -> new: 1 Observer #1 Observer #2 old: 100000.0 -> new: 10.0 Observer #1 Observer #2
  • 96. • Interface delegation for composition. • lazy for… lazy initialization. • vetoable to define a validation to be reused. • observable if you need both old and new value. • Custom delegates for everything else. Delegates - Summary
  • 97. • Std Lib has a lot of functions to help you to write a more simple, readable and concise code. • Check it out the lib internals. You’ll learn a lot! • Check it out the Kotlin Koans (https://play.kotlinlang.org/ koans). It’s a good place to start (or recap)! • Write Kotlin code, enjoy the std lib and have fun! 😉 Wrap up!
  • 98. • Kotlin Standard Functions
 https://medium.com/androiddevelopers/kotlin-standard-functions- cheat-sheet-27f032dd4326 • Mastering Kotlin standard functions: run, with, let, also and apply
 https://medium.com/@elye.project/mastering-kotlin-standard- functions-run-with-let-also-and-apply-9cd334b0ef84 • Java Friendly Kotlin
 https://codelabs.developers.google.com/codelabs/java-friendly-kotlin • Simpler Kotlin class hierarchies using class delegation
 https://proandroiddev.com/simpler-kotlin-class-hierarchies-using- class-delegation-35464106fed5 References