SlideShare une entreprise Scribd logo
1  sur  77
Télécharger pour lire hors ligne
Practical tips for building
apps with kotlin
Adit Lal | @aditlal
Agenda
What is Kotlin?
Perfect for Android
Migration guide
Best Practices
Summary - QnA
Building with kotlin
100 % interoperable
with Java
Developed by
JetBrains
Background
What is Kotlin?
Statically typed programming language for
the JVM, Android and the browser
OOP
language
with
functional
aspects
Modern and
powerful
language
Safe
concise &
readable
code
First class tool
support
What is Kotlin?
Kotlin
• Null safety
• Conciseness
• Lambdas
• Higher order functions
• Mutability protection
• Static typing + Smart Casts
We will cover :
Kotlin
Kotlin works on same byte code
Kotlin - Syntax
• Types follow variable/function names
• Functions start with fun keyword
• Default constructor in class signature
• Semicolons not required
Kotlin - Syntax
private fun sum(first: Int , second: Int): Int
{
return first + second
}
Access modifier
Keyword
Function name
Param name
Param type
Return type
Kotlin - Syntax
// Omit access modifier
fun sum(a: Int , b: Int): Int {
return a + b
}
// Inline return
fun sum(a: Int , b: Int): Int = a + b
// Omit return type
fun sum(a: Int , b: Int) = a + b
Kotlin - Syntax
val name: String ="John" // final
var name: String ="John" //Mutable
ex: name= "Johnny"
Two types of variables
val name ="John" // Types are auto-inferred
Kotlin - Syntax
//java
String sName = person.getSecretName()
//kotlin
person.secretName = “Batman”
var fName = person.secretName
Kotlin - Null Safety
NULLS ARE PART OF THE TYPE SYSTEM
Kotlin - Null Safety
Types default to non-nullable
Mark nullable with the addition of a ?
var a: String = "abc"
a = null
var b: String? = "abc"
b = null
var l = a.length
var l = b.length
// compilation error
// OK
// error: variable 'b' can be null
Kotlin - Null Safety
Helpers
Safe accessor
 ?
Elvis operator
 ?:
val toDisplay: String = serverResponse
Kotlin - Null
// if response is null, we'll display a default
message
val toDisplay: String = response ?: defaultMessage
Kotlin - Null
// cascading null safety
val maybeName: String? =
maybeNullValue?.someProperty?.name
val maybeNullValue: MyValue? = /*..*/
Kotlin - Null
// safe operation
maybeNullValue?.let {
//executed if not null
}
val maybeNullValue: MyValue? = /*..*/
Casting
if (obj instanceOf MyType) {
value =
((MyType)obj).getXValue();
} else {
// handle else
}
Kotlin - Smart casting
if (obj is MyType) {
value = obj.x
} else {
// handle else
}
Class
// Wont Compileclass Student : Person()
class Person
open class Person
Class
//It works nowclass Student : Person()
Higher order functions
Functions that can take functions as
arguments and also return function as the
output
fun <T> forEach(list: List<T>, funcToCall: (T) -> Unit) {
for (elm in list) {
funcToCall(elm)
}
}
val list = listOf("Alice", "Bob", "Claire")
forEach(list, ::println)
forEach(list, { str -> println(str) })
Higher order functions
Kotlin - Features
… and More
• Visibility Modifiers
• Companion Objects
• Nested, Sealed Classes
• Generics
• Coroutines
• Operator overloading
• Exceptions
• Annotations
• Reflection
• and more
Kotlin - Features
… and Even More
• Infix extension methods
• Interfaces
• Interface Delegation
• Property Delegation
• Destructuring
• Safe Singletons
• Init blocks
• Enums
• Multiline Strings
• Tail recursion
Perfect for
• Versatile language
• Complete interop with Java
• Compact runtime
• Enhance development speed with
less code
“But I’m comfortable and
experienced with Java.”
Common Concerns
“I don’t want to convert my entire
codebase to a new language.”
Common Concerns
•Compiled to byte code (like Java)
•No impact on performance
•Some Kotlin code faster
•Lambdas that can be inlined
•Built-in operations faster than DIY implementations
Kotlin
How to migrate
Start in small steps -
Convert a Java / Android app (side project)
Try the kotlin plugin converter
Understand how code is converted from Java to Kotlin
Experiment with kotlin features and tweak code
•Add Gradle dependencies (plugin, runtime, etc.)
•Start writing .kt files instead of .java ones
•No need to migrate everything at once
•Kotlin classes can co-exist with Java ones
• IntelliJ has a Java-to-Kotlin converter
•Not perfect but good start
• Works with pasted code
Try kotlin
Java>Kotlin
class HomeActivity : AppCompatActivity() {
override fun onCreate(b: Bundle?) {
super.onCreate(b)
setContentView(R.layout.activity_main)
val view = findViewById<View>(R.id.view)
view.alpha = 1f
}
}
Android & Kotlin
class HomeActivity : AppCompatActivity() {
override fun onCreate(b: Bundle?) {
super.onCreate(b)
setContentView(R.layout.activity_main)
val view = findViewById<View>(R.id.view)
view.alpha = 1f
}
}
Android & Kotlin
• View binding (like Butter Knife)
• No instance variables required
• How?
Android extensions
apply plugin: 'kotlin-android-extensions'
• Import synthetic layout
import kotlinx.android.synthetic.main..*
• Use view by ID
E.g. toolbar.title = "Home"
• Under the hood: synthetic calls replaced
by functions
class HomeActivity : AppCompatActivity() {
override fun onCreate(b: Bundle?) {
super.onCreate(b)
setContentView(R.layout.activity_main)
val view = findViewById<View>(R.id.view)
view.alpha = 1f
}
}
Android & Kotlin
Android extensions
class HomeActivity : AppCompatActivity() {
override fun onCreate(b: Bundle?) {
super.onCreate(b)
setContentView(R.layout.activity_main)
val view = findViewById<View>(R.id.view)
view.alpha = 1f
}
}
Android extensions
import kotlinx.android.synthetic.activity_main.*
class HomeActivity : AppCompatActivity() {
override fun onCreate(b: Bundle?) {
super.onCreate(b)
setContentView(R.layout.activity_main)
view.alpha = 1f
}
}
view.setOnClickListener{ toast(“Hello") }
Concise
view.setOnClickListener(object :
View.OnClickListener {
override fun onClick(v: View?) {
toast("Hello")
}
})
view.setOnClickListener{
view -> doSomethingWithView()
}
Concise
fun Context.inflate(
res:Int,
parent:ViewGroup? = null) : View {
return LayoutInflater.from(this)
.inflate(res, parent, false)
}
activity.inflate(R.layout.my_layout, container)
//Fragment
public class Person {
private String name;
private String surname;
private String id;
/*
Setters and getters - 20 lines
*/
@Override public boolean equals(Object o) {
//another few lines here
}
@Override public int hashCode() {
//some more lines
}
@Override public String toString() {
//some more
}
}
Data classes
Kotlin -
data class Person(
val name: String,
var surname: String = "",
val id: String
)
Data classes
Kotlin - Data classes
equals() & hashCode()
toString()
copy() function
fun evaluateObject(obj: Any): String {
return when(obj){
is String -> "Ahoy !!"
is Int -> "Lucky no is $obj"
else -> "Object is in space"
}
}
Kotlin
When expression
// Java
if(name.toLowerCase().contains(str))
{
...
}
Android
// Kotlin
if (name.contains(str, true))
{
...
}
Android
for (i in 1..100) { ... }
for (i in 0 until 100) { ... }
for (i in 2..10 step 2) { ... }
for (i in 10 downTo 1) { ... }
if (x in 1..10) { ... }
Android Kotlin tricks
fun ImageView.loadUrl(url: String) {
Glide.with(context).load(url).into(this)
}
ImageLoadingExtensions.kt
Android
//Then
ivAvatar.loadUrl("some_fancy_url")
Utils
fun View.visible() {
visibility = View.VISIBLE
}
fun View.gone() {
visibility = View.GONE
}
//call
view.visible()
Utils
fun View.setHeight(height: Int) {
val params = layoutParams
params.height = height
layoutParams = params
}
//call
tvTotalPrice.setHeight(50)
fun Activity.showOnUiThread(init: Activity.() -> Unit) : Activity {
if (!isFinishing) {
runOnUiThread {
init()
}
}
return this
}
Utils
//call
showOnUiThread(updateUIWithNewData())
fun Activity.hideKeyboard(): Boolean {
val view = currentFocus
view?.let {
val imm = getSystemService(INPUT_METHOD_SERVICE)
as InputMethodManager
return imm.hideSoftInputFromWindow(view.windowToken,
HIDE_NOT_ALWAYS)
}
return false
}
Utils
Adopting kotlin into
android code
class MyActivity : AppCompactActivity(){
// wont be init here
lateinit var obj: CustomObject
override fun onCreate(...){
obj = intent.getExtras().get("key")
// this will init the variable
}
}
lateinit Modifier
When to use lateinit
If you’re variable is mutable
If you’re sending a object from another component/
screen — ex Intent extras
lateinit Modifier
val myUtil by lazy {
SomeUtil(parameter1, parameter2)
}
Lazy Initialisation
val hashMap = HashMap<String, String>()
hashMap.put("keyA", "valueA")
hashMap.put("keyB", "valueB")
hashMap.put("keyC", "valueC")
//change to
val map = mapOf(
"keyA" to "valueA",
"keyB" to "valueB",
"keyC" to "valueC"
)
Kotlin
fun listItemsToDisplay(): List<ListItem> {
return listOf(users) + friends() + recentSearches()
}
Kotlin
fun parseResponse(response: Response?) =
when (response?.code()) {
null -> throw HTTPException(“Oh no”)
200, 201 -> parse(response.body())
in 400..499 -> throw HTTPException("Invalid request")
in 500..599 -> throw HTTPException("Server error")
else -> throw HTTPException("Error! Code
{response.code()}”)
}
Kotlin
Convert .java
Automatic migration might not always result
the best code
//Java
private static final String MY_EXTRA=
"extra_sauce";
//Kotlin
class SomeClass : AppCompatActivity() {
companion object {
}
//Other stuff here
}
private val MY_EXTRA = “extra_sauce”
Kotlin
Do this instead
//Kotlin
class SomeClass : AppCompatActivity() {
//Other stuff here
}
private val MY_EXTRA = “extra_sauce”
Kotlin
Do this instead
//Kotlin
class SomeClass : AppCompatActivity() {
//Other stuff here
}
private const val MY_EXTRA = “extra_sauce”
Kotlin
class SomeClass : AppCompatActivity() {
var someString = “”
var someValue : Payment = /*..*/
override fun onCreate(b: Bundle?) {
super.onCreate(b)
if (someValue != null)
someString = someValue!!.getCost()
}
}
Kotlin
class SomeClass : AppCompatActivity() {
var someString = “”
var someValue : Payment
override fun onCreate(b: Bundle?) {
super.onCreate(b)
if (someValue != null)
someString = someValue!!.getCost()
}
}
Kotlin
class SomeClass : AppCompatActivity() {
var someString = “”
var someValue : Payment
override fun onCreate(b: Bundle?) {
super.onCreate(b)
someValue?.let{
someValue!!.getCost()
}
}
}
run
val password: Password = PasswordGenerator().run {
seed = "someString"
hash = {s -> someHash(s)}
hashRepetitions = 1000
generate()
}
val generator = PasswordGenerator().apply {
seed = "someString"
hash = {s -> someHash(s)}
hashRepetitions = 1000
}
val pasword = generator.generate()
apply
class MyFragment : Fragment(){
companion object {
@JvmStatic
fun newInstance(b:Boolean): MyFragment {
val fragment = MyFragment()
val args = Bundle()
args.putBoolean("isValid",b)
fragment.arguments = args
return fragment
}
Fragments
Kotlin
fun handleView() {
for (item in list)
if (item is TextView)
item.text = getString(R.string.play)
else
doRandomOperationOn(item)
}
Kotlin
fun handleView() {
list.forEach { item ->
when (item) {
is TextView ->
item.text = getString(R.string.play)
else -> doRandomOperationOn(item)
}
}
}
class MyRecyclerAdapter(
val items: List,
val listener: (Item) -> Unit
){
….
}
Kotlin
recycler.adapter = MyRecyclerAdapter(items)
{
navigateToDetail(it)
}
fun View.fadeOut(duration: Long = 500):
ViewPropertyAnimator {
return animate()
.alpha(0.0f)
.setDuration(duration)
}
Optional params
icon.fadeOut() // fade out with default time (500)
icon.fadeOut(1000) // fade out with custom time
Kotlin
inline fun SharedPreferences.edit(
func: SharedPreferences.Editor.()-> Unit) {
val editor = edit()
editor.func()
editor.apply()
}
//Then
preferences.edit {
putString("foo", "bar")
putString("fizz", "buzz")
remove("username")
}
CODE
❤ Kotlin
Java to Kotlin
http://bit.ly/2glBYh8
http://bit.ly/KotlinIsAwesome
Koans -
http://bit.ly/KotlinKoans
Thank you
https://medium.com/@aditlal
@aditlal
http://bit.ly/devfestKotlin

Contenu connexe

Tendances

Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?intelliyole
 
JavaScript in 2016
JavaScript in 2016JavaScript in 2016
JavaScript in 2016Codemotion
 
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017Hardik Trivedi
 
Building Mobile Apps with Android
Building Mobile Apps with AndroidBuilding Mobile Apps with Android
Building Mobile Apps with AndroidKurt Renzo Acosta
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Languageintelliyole
 
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor ExtensionsConnect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensionsstable|kernel
 
Swift and Kotlin Presentation
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin PresentationAndrzej Sitek
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Andrey Breslav
 
Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Arnaud Giuliani
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Managementstable|kernel
 
Kotlin cheat sheet by ekito
Kotlin cheat sheet by ekitoKotlin cheat sheet by ekito
Kotlin cheat sheet by ekitoArnaud Giuliani
 
Kotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confKotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confFabio Collini
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsBartosz Kosarzycki
 
Introduction to Koltin for Android Part I
Introduction to Koltin for Android Part I Introduction to Koltin for Android Part I
Introduction to Koltin for Android Part I Atif AbbAsi
 
Connect.Tech- Level Up Your Game With TravisCI
Connect.Tech- Level Up Your Game With TravisCIConnect.Tech- Level Up Your Game With TravisCI
Connect.Tech- Level Up Your Game With TravisCIstable|kernel
 
Kotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designAndrey Breslav
 
Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Arnaud Giuliani
 

Tendances (20)

Kotlin: Why Do You Care?
Kotlin: Why Do You Care?Kotlin: Why Do You Care?
Kotlin: Why Do You Care?
 
JavaScript in 2016
JavaScript in 2016JavaScript in 2016
JavaScript in 2016
 
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017Introduction to kotlin for android app development   gdg ahmedabad dev fest 2017
Introduction to kotlin for android app development gdg ahmedabad dev fest 2017
 
Building Mobile Apps with Android
Building Mobile Apps with AndroidBuilding Mobile Apps with Android
Building Mobile Apps with Android
 
The Kotlin Programming Language
The Kotlin Programming LanguageThe Kotlin Programming Language
The Kotlin Programming Language
 
Kotlin intro
Kotlin introKotlin intro
Kotlin intro
 
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor ExtensionsConnect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions
 
Kotlin - Better Java
Kotlin - Better JavaKotlin - Better Java
Kotlin - Better Java
 
Swift and Kotlin Presentation
Swift and Kotlin PresentationSwift and Kotlin Presentation
Swift and Kotlin Presentation
 
Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011Kotlin Slides from Devoxx 2011
Kotlin Slides from Devoxx 2011
 
Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017Develop your next app with kotlin @ AndroidMakersFr 2017
Develop your next app with kotlin @ AndroidMakersFr 2017
 
Connect.Tech- Swift Memory Management
Connect.Tech- Swift Memory ManagementConnect.Tech- Swift Memory Management
Connect.Tech- Swift Memory Management
 
Kotlin cheat sheet by ekito
Kotlin cheat sheet by ekitoKotlin cheat sheet by ekito
Kotlin cheat sheet by ekito
 
Kotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confKotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community conf
 
Kotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projectsKotlin Developer Starter in Android projects
Kotlin Developer Starter in Android projects
 
Introduction to Koltin for Android Part I
Introduction to Koltin for Android Part I Introduction to Koltin for Android Part I
Introduction to Koltin for Android Part I
 
Connect.Tech- Level Up Your Game With TravisCI
Connect.Tech- Level Up Your Game With TravisCIConnect.Tech- Level Up Your Game With TravisCI
Connect.Tech- Level Up Your Game With TravisCI
 
Kotlin
KotlinKotlin
Kotlin
 
Kotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language designKotlin: Challenges in JVM language design
Kotlin: Challenges in JVM language design
 
Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017Kotlin hands on - MorningTech ekito 2017
Kotlin hands on - MorningTech ekito 2017
 

Similaire à Practical tips for building apps with kotlin

Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android developmentAdit Lal
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyMobileAcademy
 
droidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin Coroutinesdroidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin CoroutinesArthur Nagy
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 KotlinVMware Tanzu
 
From Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practiceFrom Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practiceStefanTomm
 
K is for Kotlin
K is for KotlinK is for Kotlin
K is for KotlinTechMagic
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin XPeppers
 
Kotlin/Everywhere GDG Bhubaneswar 2019
Kotlin/Everywhere GDG Bhubaneswar 2019 Kotlin/Everywhere GDG Bhubaneswar 2019
Kotlin/Everywhere GDG Bhubaneswar 2019 Sriyank Siddhartha
 
Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Mohamed Nabil, MSc.
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)Piyush Katariya
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехСбертех | SberTech
 
Rapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and KtorRapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and KtorTrayan Iliev
 
Reducing boilerplate with Kotlin, KTX and Kotlin Android Extensions
Reducing boilerplate with Kotlin, KTX and Kotlin Android ExtensionsReducing boilerplate with Kotlin, KTX and Kotlin Android Extensions
Reducing boilerplate with Kotlin, KTX and Kotlin Android ExtensionsPatrick Steiger
 

Similaire à Practical tips for building apps with kotlin (20)

Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android development
 
Kotlin Generation
Kotlin GenerationKotlin Generation
Kotlin Generation
 
Kotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRreadyKotlin for Android - Vali Iorgu - mRready
Kotlin for Android - Vali Iorgu - mRready
 
Koin Quickstart
Koin QuickstartKoin Quickstart
Koin Quickstart
 
Kotlin on android
Kotlin on androidKotlin on android
Kotlin on android
 
droidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin Coroutinesdroidcon Transylvania - Kotlin Coroutines
droidcon Transylvania - Kotlin Coroutines
 
Why Spring <3 Kotlin
Why Spring <3 KotlinWhy Spring <3 Kotlin
Why Spring <3 Kotlin
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
 
From Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practiceFrom Java to Kotlin - The first month in practice
From Java to Kotlin - The first month in practice
 
Kotlin talk
Kotlin talkKotlin talk
Kotlin talk
 
K is for Kotlin
K is for KotlinK is for Kotlin
K is for Kotlin
 
A quick and fast intro to Kotlin
A quick and fast intro to Kotlin A quick and fast intro to Kotlin
A quick and fast intro to Kotlin
 
從零開始學 Android
從零開始學 Android從零開始學 Android
從零開始學 Android
 
Kotlin/Everywhere GDG Bhubaneswar 2019
Kotlin/Everywhere GDG Bhubaneswar 2019 Kotlin/Everywhere GDG Bhubaneswar 2019
Kotlin/Everywhere GDG Bhubaneswar 2019
 
Kotlin for Android Developers - 3
Kotlin for Android Developers - 3Kotlin for Android Developers - 3
Kotlin for Android Developers - 3
 
JavaScript (without DOM)
JavaScript (without DOM)JavaScript (without DOM)
JavaScript (without DOM)
 
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТехБоремся с NPE вместе с Kotlin, Павел Шацких СберТех
Боремся с NPE вместе с Kotlin, Павел Шацких СберТех
 
Unit Testing in Kotlin
Unit Testing in KotlinUnit Testing in Kotlin
Unit Testing in Kotlin
 
Rapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and KtorRapid Web API development with Kotlin and Ktor
Rapid Web API development with Kotlin and Ktor
 
Reducing boilerplate with Kotlin, KTX and Kotlin Android Extensions
Reducing boilerplate with Kotlin, KTX and Kotlin Android ExtensionsReducing boilerplate with Kotlin, KTX and Kotlin Android Extensions
Reducing boilerplate with Kotlin, KTX and Kotlin Android Extensions
 

Dernier

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnAmarnathKambale
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...masabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park masabamasaba
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrandmasabamasaba
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park masabamasaba
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 

Dernier (20)

Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
Abortion Pills In Pretoria ](+27832195400*)[ 🏥 Women's Abortion Clinic In Pre...
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 

Practical tips for building apps with kotlin

  • 1. Practical tips for building apps with kotlin Adit Lal | @aditlal
  • 2. Agenda What is Kotlin? Perfect for Android Migration guide Best Practices Summary - QnA Building with kotlin
  • 3. 100 % interoperable with Java Developed by JetBrains Background
  • 4. What is Kotlin? Statically typed programming language for the JVM, Android and the browser
  • 5.
  • 7. Kotlin • Null safety • Conciseness • Lambdas • Higher order functions • Mutability protection • Static typing + Smart Casts We will cover :
  • 8. Kotlin Kotlin works on same byte code
  • 9. Kotlin - Syntax • Types follow variable/function names • Functions start with fun keyword • Default constructor in class signature • Semicolons not required
  • 10. Kotlin - Syntax private fun sum(first: Int , second: Int): Int { return first + second } Access modifier Keyword Function name Param name Param type Return type
  • 11. Kotlin - Syntax // Omit access modifier fun sum(a: Int , b: Int): Int { return a + b } // Inline return fun sum(a: Int , b: Int): Int = a + b // Omit return type fun sum(a: Int , b: Int) = a + b
  • 12. Kotlin - Syntax val name: String ="John" // final var name: String ="John" //Mutable ex: name= "Johnny" Two types of variables val name ="John" // Types are auto-inferred
  • 13. Kotlin - Syntax //java String sName = person.getSecretName() //kotlin person.secretName = “Batman” var fName = person.secretName
  • 14. Kotlin - Null Safety NULLS ARE PART OF THE TYPE SYSTEM
  • 15. Kotlin - Null Safety Types default to non-nullable Mark nullable with the addition of a ? var a: String = "abc" a = null var b: String? = "abc" b = null var l = a.length var l = b.length // compilation error // OK // error: variable 'b' can be null
  • 16. Kotlin - Null Safety Helpers Safe accessor  ? Elvis operator  ?:
  • 17. val toDisplay: String = serverResponse Kotlin - Null // if response is null, we'll display a default message val toDisplay: String = response ?: defaultMessage
  • 18. Kotlin - Null // cascading null safety val maybeName: String? = maybeNullValue?.someProperty?.name val maybeNullValue: MyValue? = /*..*/
  • 19. Kotlin - Null // safe operation maybeNullValue?.let { //executed if not null } val maybeNullValue: MyValue? = /*..*/
  • 20. Casting if (obj instanceOf MyType) { value = ((MyType)obj).getXValue(); } else { // handle else }
  • 21. Kotlin - Smart casting if (obj is MyType) { value = obj.x } else { // handle else }
  • 22. Class // Wont Compileclass Student : Person() class Person
  • 23. open class Person Class //It works nowclass Student : Person()
  • 24. Higher order functions Functions that can take functions as arguments and also return function as the output
  • 25. fun <T> forEach(list: List<T>, funcToCall: (T) -> Unit) { for (elm in list) { funcToCall(elm) } } val list = listOf("Alice", "Bob", "Claire") forEach(list, ::println) forEach(list, { str -> println(str) }) Higher order functions
  • 26. Kotlin - Features … and More • Visibility Modifiers • Companion Objects • Nested, Sealed Classes • Generics • Coroutines • Operator overloading • Exceptions • Annotations • Reflection • and more
  • 27. Kotlin - Features … and Even More • Infix extension methods • Interfaces • Interface Delegation • Property Delegation • Destructuring • Safe Singletons • Init blocks • Enums • Multiline Strings • Tail recursion
  • 28. Perfect for • Versatile language • Complete interop with Java • Compact runtime • Enhance development speed with less code
  • 29. “But I’m comfortable and experienced with Java.” Common Concerns
  • 30. “I don’t want to convert my entire codebase to a new language.” Common Concerns
  • 31. •Compiled to byte code (like Java) •No impact on performance •Some Kotlin code faster •Lambdas that can be inlined •Built-in operations faster than DIY implementations Kotlin
  • 32. How to migrate Start in small steps - Convert a Java / Android app (side project) Try the kotlin plugin converter Understand how code is converted from Java to Kotlin Experiment with kotlin features and tweak code
  • 33. •Add Gradle dependencies (plugin, runtime, etc.) •Start writing .kt files instead of .java ones •No need to migrate everything at once •Kotlin classes can co-exist with Java ones • IntelliJ has a Java-to-Kotlin converter •Not perfect but good start • Works with pasted code Try kotlin
  • 35. class HomeActivity : AppCompatActivity() { override fun onCreate(b: Bundle?) { super.onCreate(b) setContentView(R.layout.activity_main) val view = findViewById<View>(R.id.view) view.alpha = 1f } } Android & Kotlin
  • 36. class HomeActivity : AppCompatActivity() { override fun onCreate(b: Bundle?) { super.onCreate(b) setContentView(R.layout.activity_main) val view = findViewById<View>(R.id.view) view.alpha = 1f } } Android & Kotlin
  • 37. • View binding (like Butter Knife) • No instance variables required • How? Android extensions apply plugin: 'kotlin-android-extensions' • Import synthetic layout import kotlinx.android.synthetic.main..* • Use view by ID E.g. toolbar.title = "Home" • Under the hood: synthetic calls replaced by functions
  • 38. class HomeActivity : AppCompatActivity() { override fun onCreate(b: Bundle?) { super.onCreate(b) setContentView(R.layout.activity_main) val view = findViewById<View>(R.id.view) view.alpha = 1f } } Android & Kotlin
  • 39. Android extensions class HomeActivity : AppCompatActivity() { override fun onCreate(b: Bundle?) { super.onCreate(b) setContentView(R.layout.activity_main) val view = findViewById<View>(R.id.view) view.alpha = 1f } }
  • 40. Android extensions import kotlinx.android.synthetic.activity_main.* class HomeActivity : AppCompatActivity() { override fun onCreate(b: Bundle?) { super.onCreate(b) setContentView(R.layout.activity_main) view.alpha = 1f } }
  • 41. view.setOnClickListener{ toast(“Hello") } Concise view.setOnClickListener(object : View.OnClickListener { override fun onClick(v: View?) { toast("Hello") } }) view.setOnClickListener{ view -> doSomethingWithView() }
  • 42. Concise fun Context.inflate( res:Int, parent:ViewGroup? = null) : View { return LayoutInflater.from(this) .inflate(res, parent, false) } activity.inflate(R.layout.my_layout, container) //Fragment
  • 43. public class Person { private String name; private String surname; private String id; /* Setters and getters - 20 lines */ @Override public boolean equals(Object o) { //another few lines here } @Override public int hashCode() { //some more lines } @Override public String toString() { //some more } } Data classes
  • 44. Kotlin - data class Person( val name: String, var surname: String = "", val id: String ) Data classes
  • 45. Kotlin - Data classes equals() & hashCode() toString() copy() function
  • 46. fun evaluateObject(obj: Any): String { return when(obj){ is String -> "Ahoy !!" is Int -> "Lucky no is $obj" else -> "Object is in space" } } Kotlin When expression
  • 48. // Kotlin if (name.contains(str, true)) { ... } Android
  • 49. for (i in 1..100) { ... } for (i in 0 until 100) { ... } for (i in 2..10 step 2) { ... } for (i in 10 downTo 1) { ... } if (x in 1..10) { ... } Android Kotlin tricks
  • 50. fun ImageView.loadUrl(url: String) { Glide.with(context).load(url).into(this) } ImageLoadingExtensions.kt Android //Then ivAvatar.loadUrl("some_fancy_url")
  • 51. Utils fun View.visible() { visibility = View.VISIBLE } fun View.gone() { visibility = View.GONE } //call view.visible()
  • 52. Utils fun View.setHeight(height: Int) { val params = layoutParams params.height = height layoutParams = params } //call tvTotalPrice.setHeight(50)
  • 53. fun Activity.showOnUiThread(init: Activity.() -> Unit) : Activity { if (!isFinishing) { runOnUiThread { init() } } return this } Utils //call showOnUiThread(updateUIWithNewData())
  • 54. fun Activity.hideKeyboard(): Boolean { val view = currentFocus view?.let { val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager return imm.hideSoftInputFromWindow(view.windowToken, HIDE_NOT_ALWAYS) } return false } Utils
  • 56. class MyActivity : AppCompactActivity(){ // wont be init here lateinit var obj: CustomObject override fun onCreate(...){ obj = intent.getExtras().get("key") // this will init the variable } } lateinit Modifier
  • 57. When to use lateinit If you’re variable is mutable If you’re sending a object from another component/ screen — ex Intent extras lateinit Modifier
  • 58. val myUtil by lazy { SomeUtil(parameter1, parameter2) } Lazy Initialisation
  • 59. val hashMap = HashMap<String, String>() hashMap.put("keyA", "valueA") hashMap.put("keyB", "valueB") hashMap.put("keyC", "valueC") //change to val map = mapOf( "keyA" to "valueA", "keyB" to "valueB", "keyC" to "valueC" ) Kotlin
  • 60. fun listItemsToDisplay(): List<ListItem> { return listOf(users) + friends() + recentSearches() } Kotlin
  • 61. fun parseResponse(response: Response?) = when (response?.code()) { null -> throw HTTPException(“Oh no”) 200, 201 -> parse(response.body()) in 400..499 -> throw HTTPException("Invalid request") in 500..599 -> throw HTTPException("Server error") else -> throw HTTPException("Error! Code {response.code()}”) } Kotlin
  • 62. Convert .java Automatic migration might not always result the best code //Java private static final String MY_EXTRA= "extra_sauce"; //Kotlin class SomeClass : AppCompatActivity() { companion object { } //Other stuff here } private val MY_EXTRA = “extra_sauce”
  • 63. Kotlin Do this instead //Kotlin class SomeClass : AppCompatActivity() { //Other stuff here } private val MY_EXTRA = “extra_sauce”
  • 64. Kotlin Do this instead //Kotlin class SomeClass : AppCompatActivity() { //Other stuff here } private const val MY_EXTRA = “extra_sauce”
  • 65. Kotlin class SomeClass : AppCompatActivity() { var someString = “” var someValue : Payment = /*..*/ override fun onCreate(b: Bundle?) { super.onCreate(b) if (someValue != null) someString = someValue!!.getCost() } }
  • 66. Kotlin class SomeClass : AppCompatActivity() { var someString = “” var someValue : Payment override fun onCreate(b: Bundle?) { super.onCreate(b) if (someValue != null) someString = someValue!!.getCost() } }
  • 67. Kotlin class SomeClass : AppCompatActivity() { var someString = “” var someValue : Payment override fun onCreate(b: Bundle?) { super.onCreate(b) someValue?.let{ someValue!!.getCost() } } }
  • 68. run val password: Password = PasswordGenerator().run { seed = "someString" hash = {s -> someHash(s)} hashRepetitions = 1000 generate() }
  • 69. val generator = PasswordGenerator().apply { seed = "someString" hash = {s -> someHash(s)} hashRepetitions = 1000 } val pasword = generator.generate() apply
  • 70. class MyFragment : Fragment(){ companion object { @JvmStatic fun newInstance(b:Boolean): MyFragment { val fragment = MyFragment() val args = Bundle() args.putBoolean("isValid",b) fragment.arguments = args return fragment } Fragments
  • 71. Kotlin fun handleView() { for (item in list) if (item is TextView) item.text = getString(R.string.play) else doRandomOperationOn(item) }
  • 72. Kotlin fun handleView() { list.forEach { item -> when (item) { is TextView -> item.text = getString(R.string.play) else -> doRandomOperationOn(item) } } }
  • 73. class MyRecyclerAdapter( val items: List, val listener: (Item) -> Unit ){ …. } Kotlin recycler.adapter = MyRecyclerAdapter(items) { navigateToDetail(it) }
  • 74. fun View.fadeOut(duration: Long = 500): ViewPropertyAnimator { return animate() .alpha(0.0f) .setDuration(duration) } Optional params icon.fadeOut() // fade out with default time (500) icon.fadeOut(1000) // fade out with custom time
  • 75. Kotlin inline fun SharedPreferences.edit( func: SharedPreferences.Editor.()-> Unit) { val editor = edit() editor.func() editor.apply() } //Then preferences.edit { putString("foo", "bar") putString("fizz", "buzz") remove("username") }
  • 76. CODE ❤ Kotlin Java to Kotlin http://bit.ly/2glBYh8 http://bit.ly/KotlinIsAwesome Koans - http://bit.ly/KotlinKoans