Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin for Android Developers - DevFest Chicago / DC

Michael Evans
September 24, 2016

Kotlin for Android Developers - DevFest Chicago / DC

Michael Evans

September 24, 2016
Tweet

More Decks by Michael Evans

Other Decks in Programming

Transcript

  1. Kotlin for Android Developers
    Michael Evans
    @m_evans10
    +MichaelEvans
    michaelevans.org

    View full-size slide

  2. Kotlin for Android Developers
    Michael Evans
    LivingSocial
    @m_evans10

    View full-size slide

  3. Kotlin for Android Developers
    Michael Evans
    LivingSocial
    @m_evans10

    View full-size slide

  4. Kaitlin for Android Developers
    Michael Evans
    LivingSocial
    @m_evans10

    View full-size slide

  5. Kotlin?
    • Statically Typed
    • Developed by JetBrains
    • 100% interoperable with Java

    View full-size slide

  6. Why Kotlin?
    • Mutability problems
    • General verbosity
    • No control over platform types

    View full-size slide

  7. Nullability
    I call it my billion-dollar mistake. It was the invention of the null
    reference in 1965 […] This has led to innumerable errors,
    vulnerabilities, and system crashes, which have probably caused
    a billion dollars of pain and damage in the last forty years.

    View full-size slide

  8. Why Kotlin?
    • Type inference
    • Lambdas
    • Null safety
    • Smart casts
    • String templates
    • Higher order functions
    • Extension functions
    • Data classes
    • Default Values

    View full-size slide

  9. Getting Started

    View full-size slide

  10. Getting Started
    buildscript {

    repositories {

    mavenCentral()

    }

    dependencies {

    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.3"

    }

    }


    apply plugin: 'kotlin'


    dependencies {

    compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.3"
    }


    View full-size slide

  11. Getting Started
    buildscript {

    repositories {

    mavenCentral()

    }

    dependencies {

    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.3"

    }

    }


    apply plugin: 'kotlin'


    dependencies {

    compile "org.jetbrains.kotlin:kotlin-stdlib:1.0.3"
    }


    View full-size slide

  12. fun sum(a: Int, b: Int): Int {

    return a + b

    }
    Syntax

    View full-size slide

  13. fun sum(a: Int, b: Int): Int {

    return a + b

    }
    Syntax

    View full-size slide

  14. Syntax
    fun sum(a: Int, b: Int): Int {

    return a + b

    }

    View full-size slide

  15. fun sum(a: Int, b: Int): Int {

    return a + b

    }
    Syntax

    View full-size slide

  16. fun sum(a: Int, b: Int) = a + b

    Syntax

    View full-size slide

  17. Defining Variables
    final int a = 1;



    int x = 5;

    View full-size slide

  18. Defining Variables
    val a: Int = 1

    val b = 1


    var x = 5

    x += 1
    final int a = 1;



    int x = 5;

    View full-size slide

  19. Defining Variables
    val a: Int = 1

    val b = 1


    var x = 5

    x += 1
    final int a = 1;



    int x = 5;

    View full-size slide

  20. Properties
    public class Person {


    private String name;


    public String getName() {

    return name;

    }


    public void setName(String name) {

    this.name = name;

    }

    }

    View full-size slide

  21. Properties
    var person = Person()

    person.name = "Mike"

    val name = person.name
    class Person {


    var name: String = "Ryan"

    }

    View full-size slide

  22. String Templates
    var person = Person("Mike")


    println("Hello my name is ${person.name}")

    View full-size slide

  23. Nullability
    Make NullPointerException happen at
    compile time, not runtime.

    View full-size slide

  24. val string: String = "Mike"

    val another: String = null // does not compile


    val nullable: String? = null // ok
    Nullability

    View full-size slide

  25. Nullability
    if (files != null) {

    return files.size

    }

    View full-size slide

  26. Nullability
    println(person?.name)


    val email = data["email"] ?: "[email protected]"


    data?.let {

    // execute this block if not null


    println(files!!.size)

    View full-size slide

  27. Nullability
    println(person?.name?.length)


    val email = data["email"] ?: "[email protected]"


    data?.let {

    // execute this block if not null


    println(files!!.size)

    View full-size slide

  28. Nullability
    println(person?.name?.length)


    val email = data["email"] ?: "[email protected]"


    data?.let {

    // execute this block if not null


    println(files!!.size)

    View full-size slide

  29. Nullability
    println(person?.name?.length)


    val email = data["email"] ?: "[email protected]"

    println(files!!.size)

    View full-size slide

  30. fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {

    Toast.makeText(this, message, length).show()

    }
    Default Values

    View full-size slide

  31. fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {

    Toast.makeText(this, message, length).show()

    }
    toast("Hello")

    toast("Hello", Toast.LENGTH_LONG)

    toast("Hello", length = Toast.LENGTH_LONG)
    Default Values

    View full-size slide

  32. Extension Functions
    fun List.swap(index1: Int, index2: Int) {

    val tmp = this[index1]

    this[index1] = this[index2]

    this[index2] = tmp

    }

    View full-size slide

  33. fun Activity.toast(message: CharSequence, duration:
    Int = Toast.LENGTH_SHORT) {

    Toast.makeText(this, message, duration).show()

    }
    fun List.swap(index1: Int, index2: Int) {

    val tmp = this[index1]

    this[index1] = this[index2]

    this[index2] = tmp

    }
    Extension Functions

    View full-size slide

  34. { it.isEmpty() }

    { it.length == 10 }

    { isPalindrome(it) }
    Function Expressions

    View full-size slide

  35. { it.isEmpty() }

    { it.length == 10 }

    { isPalindrome(it) }
    Function Expressions

    View full-size slide

  36. { it.isEmpty() }

    { it.length == 10 }

    { isPalindrome(it) }
    Function Expressions

    View full-size slide

  37. val isEmpty: (String) -> Boolean = { it.isEmpty() }

    val exactly10: (String) -> Boolean = { it.length == 10 }

    val palindrome: (String) -> Boolean = { isPalindrome(it) }
    Function Expressions

    View full-size slide

  38. fun List.filter(predicate: (T) -> Boolean): List {

    // ...

    }
    Higher order functions

    View full-size slide

  39. Higher order functions
    fun List.filter(predicate: (T) -> Boolean): List {

    val newList = ArrayList()

    for (item in this) {

    if(predicate(item)) {

    newList.add(item)

    }

    }

    return newList

    }

    View full-size slide

  40. fun List.filter(predicate: (T) -> Boolean): List {

    // ...

    }
    Higher order functions
    val names = listOf("Mike", "John", "Bob")

    names.filter { it == "Mike" } // ["Mike"]

    names.filter(palindrome) // ["Bob"]

    View full-size slide

  41. Extension Functions
    Picasso.with(imageView.getContext())

    .load(imageUrl)

    .into(imageView);

    View full-size slide

  42. Extension Functions
    fun ImageView.load(url: String) {

    Picasso.with(context).load(url).into(this)

    }

    View full-size slide

  43. Extension Functions
    fun ImageView.load(url: String) {

    Picasso.with(context).load(url).into(this)

    }
    imageView.load("http://...")

    View full-size slide

  44. inline fun supportsLollipop(code: () -> Unit) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    code.invoke()

    }

    }
    Inline Functions

    View full-size slide

  45. supportsLollipop {

    getWindow().setStatusBarColor(Color.BLACK)

    }
    inline fun supportsLollipop(code: () -> Unit) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

    code.invoke()

    }

    }
    Inline Functions

    View full-size slide

  46. public class ContactsAdapter extends RecyclerView.Adapter {

    interface ContactClickListener {

    void onContactClicked(Contact contact);

    }

    View full-size slide

  47. public class ContactsAdapter extends RecyclerView.Adapter {

    interface ContactClickListener {

    void onContactClicked(Contact contact);

    }
    recycler.setAdapter(new ContactsAdapter(contacts,
    new ContactsAdapter.ContactClickListener() {

    @Override

    public void onContactClicked(ContactsAdapter.Contact contact) {


    }

    }));

    View full-size slide

  48. recycler.adapter = ContactsAdapter(contacts) {

    navigateToDetail(it)

    }


    class ContactsAdapter(val contacts: List,

    val listener: (Contact) -> Unit)


    itemView.setOnClickListener { listener(contact) }

    View full-size slide

  49. recycler.adapter = ContactsAdapter(contacts) {

    navigateToDetail(it)

    }


    class ContactsAdapter(val contacts: List,

    val listener: (Contact) -> Unit)


    itemView.setOnClickListener { listener(contact) }

    View full-size slide

  50. recycler.adapter = ContactsAdapter(contacts) {

    navigateToDetail(it)

    }


    class ContactsAdapter(val contacts: List,

    val listener: (Contact) -> Unit)


    itemView.setOnClickListener { listener(contact) }

    View full-size slide

  51. Extension Function Expressions

    View full-size slide

  52. Extension Function Expressions
    SharedPreferences.Editor editor =
    getSharedPreferences("prefs", 0).edit();

    editor.putString("this", "that");

    editor.apply();

    View full-size slide

  53. inline fun SharedPreferences.edit(
    func: SharedPreferences.Editor.() -> Unit) {

    val editor = edit()

    editor.func()

    editor.apply()

    }


    Extension Function Expressions

    View full-size slide

  54. inline fun SharedPreferences.edit(
    func: SharedPreferences.Editor.() -> Unit) {

    val editor = edit()

    editor.func()

    editor.apply()

    }


    preferences.edit {

    putString("foo", "bar")

    putString("fizz", "buzz")

    remove("username")

    }
    Extension Function Expressions

    View full-size slide

  55. inline fun SharedPreferences.edit(
    func: SharedPreferences.Editor.() -> Unit) {

    val editor = edit()

    editor.func()

    editor.apply()

    }


    fun SharedPreferences.Editor.set(pair:
    Pair) =

    putString(pair.first, pair.second)
    Extension Function Expressions

    View full-size slide

  56. preferences.edit {

    set("foo" to "bar")

    set("fizz" to "buzz")

    remove("username")

    }
    Extension Function Expressions

    View full-size slide

  57. verticalLayout {

    padding = dip(30)

    editText {

    hint = "Name"

    textSize = 24f

    }

    editText {

    hint = "Password"

    textSize = 24f

    }

    button("Login") {

    textSize = 26f

    }

    }
    Anko

    View full-size slide

  58. apply plugin: 'kotlin-android-extensions'
    import kotlinx.android.synthetic.main.activity_main.*

    textView.setText("Hello, world!")
    Kotlin Extensions for Android

    View full-size slide

  59. Getting started?

    View full-size slide

  60. Java Interoperability

    View full-size slide

  61. Java Interoperability
    class Person {

    private String name;


    public void setName(String name) {

    this.name = name;

    }

    }

    View full-size slide

  62. var person = Person()

    person.name = "name"
    Java Interoperability
    class Person {

    private String name;


    public void setName(String name) {

    this.name = name;

    }

    }

    View full-size slide

  63. Java Interoperability - Extensions

    View full-size slide

  64. // com/example/util/DateExtensions.kt

    fun Date.isTuesday() = day == 2


    // com/example/util/DateExtensionsKt.java

    static boolean isTuesday(Date date) {

    return date.getDay() == 2;

    }
    Java Interoperability - Extensions

    View full-size slide

  65. // com/example/util/DateExtensions.kt

    fun Date.isTuesday() = day == 2


    // com/example/util/DateExtensionsKt.java

    static boolean isTuesday(Date date) {

    return date.getDay() == 2;

    }
    Java Interoperability - Extensions

    View full-size slide

  66. // com/example/util/DateExtensions.kt
    @file:JvmName("DateUtils")
    fun Date.isTuesday() = day == 2


    // com/example/util/DateUtils.java

    static boolean isTuesday(Date date) {

    return date.getDay() == 2;

    }
    Java Interoperability - Extensions

    View full-size slide

  67. Implement Tests in Kotlin

    View full-size slide

  68. Data Classes
    class Person {

    private String name;

    private int age;


    public String getName() {

    return name;

    }


    public int getAge() {

    return age;

    }

    }

    View full-size slide

  69. Data Classes
    @Override public boolean equals(Object o) {

    if (this == o) return true;

    if (o == null || getClass() != o.getClass()) return false;


    Person person = (Person) o;


    if (age != person.age) return false;

    return name != null ? name.equals(person.name) : person.name == null;

    }


    @Override public int hashCode() {

    int result = name != null ? name.hashCode() : 0;

    result = 31 * result + age;

    return result;

    }


    @Override public String toString() {

    return super.toString();

    }

    }

    View full-size slide

  70. Data Classes
    data class Person(val name: String, val age: Int)

    View full-size slide

  71. Convert Java File to Kotlin
    Kotlin Scripts for Gradle

    View full-size slide

  72. More Info
    • https://kotlinlang.org
    • Koans
    • https://kotlinlang.org/docs/tutorials/koans.html
    • https://leanpub.com/kotlin-for-android-developers

    View full-size slide

  73. Questions?
    Michael Evans
    @m_evans10
    +MichaelEvans
    michaelevans.org

    View full-size slide

  74. Questions?
    Michael Evans
    @m_evans10
    +MichaelEvans
    michaelevans.org
    STICKERS!

    View full-size slide