Android джедая путь

Ivan Balaksha

Что не так с Java?

Проверяемые исключения

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

Синтаксис анонимных классов

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

Статически типизированный язык программирования для Android, JVM и веб разработки

 

100% совместимость с Java™

  • Выразительность
  • Безопасность
  • Универсальность
  • Совместимость

Почему Kotlin?

Выразительность

fun myFunction() {
    var a: Int = 1
    val b = 2
    val s: String = "test"
    val f = 2f
}

fun sum(first: Int, second: Int) : Int {
    return first + second
}
val firstName : String = "Ivan"
val lastName : String = "Balaksha"
var age : Int = 21

Свойства + Вывод типов*

val firstName = "Ivan"
val lastName = "Balaksha"
var age = 21

*JEP 286: Local-Variable Type Inference

val i : Int = ...
val f : Float = ...
val d : Double = ...
 

Отсутствие примитивных типов

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

Лямбда выражения

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

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

Лямбда выражения

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

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


button.setOnClickListener { doAnything() }

Лямбда выражения

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

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


button.setOnClickListener { doAnything() }


button.onClick { doAnything() }  (Anko)

Лямбда выражения


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

Дата классы

equals()

hashCode()

toString()

Автоматически генерируются:

 

Стандартные значения для параметров функции

    ...

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

}

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

Именованный аргумент

"Single-expression" функции


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

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

Строковые шаблоны

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

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

Умные преобразования

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

Функции расширения

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 

 

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(...)
}

Коллекции

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

...

Коллекции

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

Безопасность

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

Java небезопасна

Мое приложение упало.

Что случилось?

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

Java небезопасна

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)

Ошибка выполнения

Nullable типы

val user : User? = ...

var notification : Notification? = ...

Оператор безопасного вызова

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

Элвис оператор

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

Ошибка компиляции

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

ничего не напечатает

var name : String = "testString"
name = null

Ошибка компиляции

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

Ошибка выполнения

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")
    ...
}

Ошибка компиляции

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

Nullable строка

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

Nullable строка

Оператор безопасного вызова

let

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

Безопасные преобразования

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

Универсальность

Многоцелевой язык программирования, позволяющий создавать приложения любых типов

  • Android
  • Back-end
  • Front-end(Javascript)
  • ...

Совместимость

Совместимость

Java code

Kotlin code

javac

kotlinc

bytecode

DEX

Время компиляции

Java

Kotlin

Scala

+

+/–

Размер стандартной библиотеки

+

(~7k методов)

(~50k методов)

Что-то еще?

  • Ленивые свойства
  • Интерфейсы с поддержкой "стандартных методов"
  • Перезагрузка операторов
  • Anko
  • Android Extension Plugin

Что планируется в Kotlin 1.1

  • async-await
  • type aliases
  • улучшенная поддержка Java 8
  • поддержка Java 9 ( Jigsaw)
  • Javascript backend
  • закончить спецификацию языка

Хотите использовать у себя в проекте?

  1. Установить Kotlin плагин
  2. Tools->Kotlin->Configure Kotlin in Project
  3. Gradle sync

Ресурсы

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

 

http://try.kotlinlang.org

Q/A

Ivan Balaksha

 

@VanyaBalaksha

 

https://slides.com/ivanbalaksha

Kotlin - Android джедая путь(RUS)

By Ivan Balaksha

Kotlin - Android джедая путь(RUS)

  • 1,453