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

Kotlin for Android Developers - DevFest Chicago / DC

Kotlin for Android Developers - DevFest Chicago / DC

48fd642048ccd225ddaffcada7a6d407?s=128

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

  2. Kotlin for Android Developers Michael Evans LivingSocial @m_evans10

  3. Kotlin for Android Developers Michael Evans LivingSocial @m_evans10

  4. Kaitlin for Android Developers Michael Evans LivingSocial @m_evans10

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

    interoperable with Java
  6. Why Kotlin? • Mutability problems • General verbosity • No

    control over platform types
  7. Nullability

  8. 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.
  9. Why Kotlin? • Type inference • Lambdas • Null safety

    • Smart casts • String templates • Higher order functions • Extension functions • Data classes • Default Values
  10. Getting Started

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

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

  13. Syntax

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

    b
 } Syntax
  15. fun sum(a: Int, b: Int): Int {
 return a +

    b
 } Syntax
  16. Syntax fun sum(a: Int, b: Int): Int {
 return a

    + b
 }
  17. fun sum(a: Int, b: Int): Int {
 return a +

    b
 } Syntax
  18. fun sum(a: Int, b: Int) = a + b
 Syntax

  19. Defining Variables final int a = 1;
 
 
 int

    x = 5;
  20. Defining Variables val a: Int = 1
 val b =

    1
 
 var x = 5
 x += 1 final int a = 1;
 
 
 int x = 5;
  21. Defining Variables val a: Int = 1
 val b =

    1
 
 var x = 5
 x += 1 final int a = 1;
 
 
 int x = 5;
  22. Properties public class Person {
 
 private String name;
 


    public String getName() {
 return name;
 }
 
 public void setName(String name) {
 this.name = name;
 }
 }
  23. Properties var person = Person()
 person.name = "Mike"
 val name

    = person.name class Person {
 
 var name: String = "Ryan"
 }
  24. String Templates var person = Person("Mike")
 
 println("Hello my name

    is ${person.name}")
  25. Nullability Make NullPointerException happen at compile time, not runtime.

  26. val string: String = "Mike"
 val another: String = null

    // does not compile
 
 val nullable: String? = null // ok Nullability
  27. Nullability if (files != null) {
 return files.size
 }

  28. Nullability println(person?.name)
 
 val email = data["email"] ?: "foo@bar.com"
 


    data?.let {
 // execute this block if not null
 
 println(files!!.size)
  29. Nullability println(person?.name?.length)
 
 val email = data["email"] ?: "foo@bar.com"
 


    data?.let {
 // execute this block if not null
 
 println(files!!.size)
  30. Nullability println(person?.name?.length)
 
 val email = data["email"] ?: "foo@bar.com"
 


    data?.let {
 // execute this block if not null
 
 println(files!!.size)
  31. Nullability println(person?.name?.length)
 
 val email = data["email"] ?: "foo@bar.com" 


    println(files!!.size)
  32. fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {
 Toast.makeText(this, message,

    length).show()
 } Default Values
  33. 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
  34. Extension Functions fun List.swap(index1: Int, index2: Int) {
 val tmp

    = this[index1]
 this[index1] = this[index2]
 this[index2] = tmp
 }
  35. 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
  36. { it.isEmpty() } 
 { it.length == 10 } 


    { isPalindrome(it) } Function Expressions
  37. { it.isEmpty() } 
 { it.length == 10 } 


    { isPalindrome(it) } Function Expressions
  38. { it.isEmpty() } 
 { it.length == 10 } 


    { isPalindrome(it) } Function Expressions
  39. val isEmpty: (String) -> Boolean = { it.isEmpty() } 


    val exactly10: (String) -> Boolean = { it.length == 10 } 
 val palindrome: (String) -> Boolean = { isPalindrome(it) } Function Expressions
  40. fun <T> List<T>.filter(predicate: (T) -> Boolean): List<T> {
 // ...


    } Higher order functions
  41. Higher order functions fun <T> List<T>.filter(predicate: (T) -> Boolean): List<T>

    {
 val newList = ArrayList<T>()
 for (item in this) {
 if(predicate(item)) {
 newList.add(item)
 }
 }
 return newList
 }
  42. fun <T> List<T>.filter(predicate: (T) -> Boolean): List<T> {
 // ...


    } Higher order functions val names = listOf("Mike", "John", "Bob")
 names.filter { it == "Mike" } // ["Mike"]
 names.filter(palindrome) // ["Bob"]
  43. Examples

  44. Extension Functions Picasso.with(imageView.getContext())
 .load(imageUrl)
 .into(imageView);

  45. Extension Functions fun ImageView.load(url: String) {
 Picasso.with(context).load(url).into(this)
 }

  46. Extension Functions fun ImageView.load(url: String) {
 Picasso.with(context).load(url).into(this)
 } imageView.load("http://...")

  47. inline fun supportsLollipop(code: () -> Unit) {
 if (Build.VERSION.SDK_INT >=

    Build.VERSION_CODES.LOLLIPOP) {
 code.invoke()
 }
 } Inline Functions
  48. supportsLollipop {
 getWindow().setStatusBarColor(Color.BLACK)
 } inline fun supportsLollipop(code: () -> Unit)

    {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 code.invoke()
 }
 } Inline Functions
  49. public class ContactsAdapter extends RecyclerView.Adapter {
 interface ContactClickListener {
 void

    onContactClicked(Contact contact);
 }
  50. 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) {
 
 }
 }));
  51. recycler.adapter = ContactsAdapter(contacts) {
 navigateToDetail(it)
 }
 
 class ContactsAdapter(val contacts:

    List<Contact>,
 val listener: (Contact) -> Unit)
 
 itemView.setOnClickListener { listener(contact) }
  52. recycler.adapter = ContactsAdapter(contacts) {
 navigateToDetail(it)
 }
 
 class ContactsAdapter(val contacts:

    List<Contact>,
 val listener: (Contact) -> Unit)
 
 itemView.setOnClickListener { listener(contact) }
  53. recycler.adapter = ContactsAdapter(contacts) {
 navigateToDetail(it)
 }
 
 class ContactsAdapter(val contacts:

    List<Contact>,
 val listener: (Contact) -> Unit)
 
 itemView.setOnClickListener { listener(contact) }
  54. Extension Function Expressions

  55. Extension Function Expressions SharedPreferences.Editor editor = getSharedPreferences("prefs", 0).edit();
 editor.putString("this", "that");


    editor.apply();
  56. inline fun SharedPreferences.edit( func: SharedPreferences.Editor.() -> Unit) {
 val editor

    = edit()
 editor.func()
 editor.apply()
 }
 
 Extension Function Expressions
  57. 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
  58. inline fun SharedPreferences.edit( func: SharedPreferences.Editor.() -> Unit) {
 val editor

    = edit()
 editor.func()
 editor.apply()
 }
 
 fun SharedPreferences.Editor.set(pair: Pair<String, String>) =
 putString(pair.first, pair.second) Extension Function Expressions
  59. preferences.edit {
 set("foo" to "bar")
 set("fizz" to "buzz")
 remove("username")
 }

    Extension Function Expressions
  60. Libraries

  61. verticalLayout {
 padding = dip(30)
 editText {
 hint = "Name"


    textSize = 24f
 }
 editText {
 hint = "Password"
 textSize = 24f
 }
 button("Login") {
 textSize = 26f
 }
 } Anko
  62. apply plugin: 'kotlin-android-extensions' import kotlinx.android.synthetic.main.activity_main.* … textView.setText("Hello, world!") Kotlin Extensions

    for Android
  63. Getting started?

  64. Java Interoperability

  65. Java Interoperability class Person {
 private String name;
 
 public

    void setName(String name) {
 this.name = name;
 }
 }
  66. var person = Person()
 person.name = "name" Java Interoperability class

    Person {
 private String name;
 
 public void setName(String name) {
 this.name = name;
 }
 }
  67. Java Interoperability - Extensions

  68. // 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
  69. // 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
  70. // 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
  71. Implement Tests in Kotlin

  72. Data Classes class Person {
 private String name;
 private int

    age;
 
 public String getName() {
 return name;
 }
 
 public int getAge() {
 return age;
 }
 }
  73. 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();
 }
 }
  74. Data Classes data class Person(val name: String, val age: Int)

  75. Convert Java File to Kotlin Kotlin Scripts for Gradle

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

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

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