The path of Android jedi 

is

What's wrong with Java?

Checked Exceptions

public void readFileLineByLine(){
    BufferedReader buffReader = null;
    try {
        ...
    } catch (IOException ioe){
        ...
    } finally {
        if (buffReader != null){
            try {
                buffReader.close();
            } catch (IOException ioe1){
                ...
            }
        }
    }
    ...
}

        

NPE HELL*

public void doSmth(JavaUser user){
    if(user != null){
        String login = user.getLogin();
        if(login != null){
            System.out.println("Hello " + login);
        }
    }
}

*JSR 305: Annotations for Software Defect Detection

Anonymous class syntax

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        ...
    }
});

Statically typed programming language
for the JVM, Android and the browser


100% interoperable with Java™

  • Concise
  • Safe
  • Versatile
  • Interoperable

 

Why Kotlin?

Concise

val firstName : String = "Ivan"
val lastName : String = "Balaksha"
var age : Int = 21

Properties + Type inference

val firstName = "Ivan"
val lastName = "Balaksha"
var age = 21
button.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        doAnything()
    }
})

Lambda expressions

button.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        doAnything()
    }
})

button.setOnClickListener(View.OnClickListener { 
    doAnything() 
})

Lambda expressions

button.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        doAnything()
    }
})

button.setOnClickListener(View.OnClickListener { 
    doAnything() 
})


button.setOnClickListener { doAnything() }

Lambda expressions

button.setOnClickListener(object : View.OnClickListener{
    override fun onClick(v: View?) {
        doAnything()
    }
})

button.setOnClickListener(View.OnClickListener { 
    doAnything() 
})


button.setOnClickListener { doAnything() }


button.onClick { doAnything() }  (Anko)

Lambda expressions


data class KotlinUser(val login : String,val password : String)

Data classes

equals()

hashCode()

toString()

Provides

Default values for function parameters

    ...

    addContact("Ivan", "Balaksha", email = "test@test.test")

}

fun addContact(firstName: String, 
               lastName: String,
               phone: String = "", 
               email: String = ""){
    ...        
}

Named Argument

Single-expression functions


 fun findUser(id : Int) = dataStore.find(id) 

 fun findUser(id : Int) : User{
     return dataStore.find(id)
 }

String templates

val user = KotlinUser("admin","pwd")

val userInfo = "Login: ${user.login} Password: ${user.password}"

Smart casts

fun demo(x: Any) {
    if (x is String) {
        print(x.length)
    }else if(x is Int){
        print(x + x)    
    }
}

Extension functions

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        this.alert {  }
        alert {  }
        ...
    }
}

class BlankFragment : Fragment() {
    override fun onCreateView(...): View? {
        getActivity().alert {  }
        activity.alert {  }
        return super.onCreateView(inflater, container, savedInstanceState)
    }
}
fun Context.alert(init: AlertDialogBuilder.() -> Unit) 
    = AlertDialogBuilder(this).apply { init() }

When expression

val type = ...
val imageUrl = when(type){
    1 -> ...
    2 -> ...
    3 -> ...
    else -> ...
}

with

recyclerView.adapter = ...
recyclerView.layoutManager = ...
recyclerView.visibility = ...
recyclerView.addOnItemTouchListener(...)
with(recyclerView) {
    adapter = ...
    layoutManager = ...
    visibility = ...
    addOnItemTouchListener(...)
}

Collections

associate

binarysearch

count

distinct/distinctBy

drop

dropWhile

find

fold

first

filter

flatMap

forEach

groupBy

getOrElse

indexOfFirst

indexOfLast

map

max/min

reduce

take

takeWhile

sort/sortBy

zip

...

Collections

names
    .filter { it.startsWith("A") }
    .sortedBy { it }
    .map { it.toUpperCase() }
    .forEach { print(it) }

Safe

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String info = savedInstanceState.getString("info");
    ...
}

Null-Safety

My app is crashed. What happened?

Java

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    String info = savedInstanceState.getString("info");
    ...
}

Null-Safety

Caused by: java.lang.NullPointerException: 
Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' 
on a null object reference
at pre.MainActivity.onCreate(MainActivity.java:17)

Runtime exception

Nullable types

val user : User? = ...

var notification : Notification? = ...

Safe call operator

 
 val name : String? = ...
 val length = name?.lenght

Elvis operator

 
 val name : String? = ...
 val length = name?.length ?: 0
val name : String = null

Compile time validation

Compilation error

val name : String? = null
println(name?.length)

Nothing do

val name : String = "testString"
name = null

Compilation error

val name : String? = null
println(name!!.length)

Runtime exception

Null-Safety

Error:(15, 47) 
Only safe (?.) or non-null asserted (!!.) 
calls are allowed on a nullable receiver of type android.os.Bundle?
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val info : String = savedInstanceState.getString("info")
    ...
}

Compilation error

Let's fix it!

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val info : String? = savedInstanceState?.getString("info")
    ...
}

Nullable string

Let's fix it!

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val info : String? = savedInstanceState?.getString("info")
    ...
}

Nullable string

Safe call operator

let

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val info : String? = savedInstanceState?.getString("info")
    info?.let { process(it) }
    ...
}

Safe cast

fun process(a : Any){
    val aInt: Int? = a as? Int
    ...
}

Versatile

Multi-purpose language allowing you to build any type of application

  • Android
  • Back-end
  • Front-end
  • ...

Interoperable

Interoperable

Java code

Kotlin code

javac

kotlinc

bytecode

DEX

Compilation time

Java

Kotlin

Scala

+

+/–

Standard library size

+

(~7k methods)

(~50k methods)

Anything else?

Lazy properties
Interfaces with "default methods"

Operator Overloading
Anko
Android Extension Plugin

Roadmap Kotlin 1.1

  • async-await
  • type aliases
  • improved Java 8 support
  • Java 9 support (esp. Jigsaw)
  • Javascript backend
  • improved interactive experience (cf. Scala Worksheets)
  • complete language specification

Resources

https://kotlinlang.org/docs/reference/

 

http://try.kotlinlang.org

Q/A

The path of Android jedi Kotlin is(Eng)

By Ivan Balaksha

The path of Android jedi Kotlin is(Eng)

  • 786