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

Exploring Kotlin on Android

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Exploring Kotlin on Android

at Expedia

Avatar for Deepanshu

Deepanshu

May 03, 2016
Tweet

Other Decks in Programming

Transcript

  1. What is Kotlin? • Statically typed programming language   •

    JVM-based language developed by JetBrains • From industry not academia • 100% inter-operable with the Java language Open Source - https://github.com/JetBrains/kotlin
  2. Why Kotlin Concise - Drastically reduce the amount of boilerplate

    code you need to write. Safe - Avoid entire classes of errors such as null pointer exceptions. Versatile - Build server-side applications, Android apps or front-end code running in the browser.
  3. Kotlin in Expedia Android Kotlin code is at 23% and

    rising. Refactoring started mid 2015. Hotels, Packages, Flights, Services and MockWebServer & tests classes are 90% in Kotlin Cars/LX/Legacy tablet code still in java. Other teams in Expedia are experimenting with Kotlin in the web.
  4. Features • Null type and safety • Lambdas • Optional

    params • Data classes • Extension functions • Delegates • Smart Casting
  5. Kotlin Roadmap for Android • Incremental compilation • support for

    Jack and Jill toolchain • Instant run works for cold swaps right now not for hot swaps • Lint checks in Kotlin 1.0.2
  6. Defining Functions fun sum(a: Int, b: Int): Int {
 return

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

  7. fun printSum(a: Int, b: Int): Unit {
 print(a + b)


    } fun printSum(a: Int, b: Int) {
 print(a + b)
 } Defining Functions
  8. fun doSomething(): Int {
 val a: Int = 1
 val

    b = 1 
 val c: Int 
 c = a + b
 
 return c
 } Defining local variables
  9. fun doSomething(): Int {
 val a: Int = 1
 var

    b = 1 val c: Int b += 5
 c = a + b
 
 return c
 } Defining local variables
  10. Using conditional expressions fun doSomething(a: Int, b: Int): Int {


    if (a > b)
 return a
 else
 return b
 }
  11. Using conditional expressions fun doSomething(a: Int, b: Int): Int {


    if (a > b)
 return a
 else
 return b
 } fun doSomething(a: Int, b: Int) = if (a > b) a else b

  12. Using a for loop fun doSomething(args: Array<String>) {
 for (arg

    in args)
 print(arg)
 } fun doSomething(args: Array<String>) {
 for (i in args.indices)
 print(args[i])
 }
  13. Using when expression fun doSomething(obj: Any) {
 when (obj) {


    1 -> print("One")
 "Hello" -> print("Kotlin")
 is Long -> print("Long")
 !is String -> print(“!string")
 else -> print("Unknown")
 }
 }
  14. Using ranges fun doSomething(x: Int, y: Int) {
 if (x

    in 1..y - 1)
 print("In")
 
 for (x in 1..5)
 print(“N") if (x !in 1..y - 1)
 print(“In") }
  15. Using ranges fun doSomething(x: Int, y: Int) {
 if (x

    in 1..y - 1)
 print("In")
 
 for (x in 1..5)
 print("N")
 
 if (x !in 1..y - 1)
 print(“In") 
 }
  16. Using ranges fun doSomething(x: Int, y: Int) {
 if (x

    in 1..y - 1)
 print("In")
 
 for (x in 1..5)
 print("N")
 
 if (x !in 1..y - 1)
 print(“In") 
 }
  17. Class in Java public class SomeClass {
 
 private String

    variable;
 private final String defaultVar;
 
 SomeClass(String variable) {
 this.variable = variable;
 this.defaultVar = "Java";
 }
 
 SomeClass(String variable, String defaultVar) {
 this.variable = variable;
 this.defaultVar = defaultVar;
 }
 } // Use new SomeClass("Kotlin", "Java");
 new SomeClass("Kotlin");
  18. Class in Kotlin class SomeClass(var variable: String, val defaultValue: String

    = "Java") {
 }
 // Use
 SomeClass("Kotlin", "Java")
 SomeClass("Kotlin")
  19. Lambdas //In Kotlin fun doSomething() {
 val items = ArrayList<String>()


    items.sortBy { it.length }
 } //In Java ArrayList<String> items = new ArrayList();
 Collections.sort(items, new Comparator<String>(){
 @Override
 public int compare(String s1, String s2) {
 return s1.length() - s2.length();
 }
 });
  20. //In Kotlin button.setOnClickListener {
 Toast.makeText(this, "Button",
 Toast.LENGTH_LONG).show()
 } //In Java

    button.setOnClickListener(new View.OnClickListener(){
 public void onClick(View v) {
 Toast.makeText(this.MainActivity, "Button",
 Toast.LENGTH_LONG).show();
 }
 });
  21. class Vehicle(var value: String) {
 }
 
 fun doSomething() {


    val type = Vehicle("Car")
 println("${type.value}")
 }
  22. class Vehicle(var value: String) {
 }
 
 fun doSomething() {


    val type = Vehicle("Car")
 println("${type.value}")
 }
  23. class Vehicle(var value: String) {
 }
 
 fun doSomething() {


    val type = Vehicle("Car")
 println("${type.value}")
 }
  24. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val type = Vehicle("Car")
 type.print()
 }
  25. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val type = Vehicle("Car")
 type.print()
 }
  26. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val types = listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike"))
 
 }
  27. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val types = listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike"))
 
 for (type in types) {
 type.print()
 }
 }

  28. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val types = listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike"))
 
 types.forEach { type ->
 type.print()
 }
 }
  29. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val types = listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike"))
 
 types.forEach { it.print() }
 }
  30. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 val types = listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike"))
 
 types.forEach { it.print() }
 }
  31. class Vehicle(var value: String) {
 fun print() = println("$value")
 }


    
 fun doSomething() {
 listOf(
 Vehicle("Car"),
 Vehicle("Truck"),
 Vehicle("Bike")
 ).forEach { it.print() }
 }
  32. open class Vehicle(var value: String) {
 fun print() = println("$value")


    }
 
 class Car(var type: String) : Vehicle(type){
 }
 
 fun doSomething() {
 listOf(
 Car("Car"),
 Vehicle("Truck"),
 Vehicle("Bike")
 ).forEach{it.print()}
 }
  33. open class Vehicle(var value: String) {
 fun print() = println("$value")


    }
 
 class Car(var type: String) : Vehicle(type){
 }
 
 fun doSomething() {
 listOf(
 Car("Car"),
 Vehicle("Truck"),
 Vehicle("Bike")
 ).forEach{it.print()}
 }
  34. open class Vehicle(var value: String) {
 open fun print() =

    println("$value")
 }
 
 class Car(var type: String) : Vehicle(type){
 override fun print() = println("Yo, Its a $value")
 }
 
 fun doSomething() {
 listOf(
 Car("Car"),
 Vehicle("Truck"),
 Vehicle("Bike")
 ).forEach{it.print()}
 }
  35. open class Vehicle(var value: String) {
 open fun print() =

    println("$value")
 }
 
 class Car(var type: String) : Vehicle(type){
 override fun print() = println("Yo, Its a $value")
 }
 
 fun doSomething() {
 listOf(
 Car("Car"),
 Vehicle("Truck"),
 Vehicle("Bike")
 ).forEach{it.print()}
 }
  36. Nullability I call it my billion-dollar mistake. It was the

    invention of the null reference …. 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. -Sir Charles Antony Richard Hoare
  37. Null and type safety fun doSomething() {
 var a: String

    = "abc"
 a = null // compilation error
 }
  38. fun doSomething() {
 var a: String = "abc"
 a =

    null // compilation error
 
 var b: String? = "abc"
 b = null // ok
 } Null and type safety
  39. fun doSomething() {
 var a: String = "abc"
 
 var

    b: String? = "abc"
 b = null // ok
 
 val l = a.length
 
 } Null and type safety
  40. 
 fun doSomething() {
 var a: String = "abc"
 


    var b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l2 = b.length // error:variable 'b' can be null
 
 } Null and type safety
  41. Checking for null in conditions fun doSomething() {
 var a:

    String = "abc"
 
 var b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l = if (b != null) b.length else -1
 
 }
  42. Safe Calls fun doSomething() {
 var a: String = "abc"


    
 var b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l2 = b?.length 
 
 }
  43. Elvis Operator fun doSomething() {
 var a: String = "abc"


    
 var b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l = if (b != null) b.length else -1
 
 }
  44. fun doSomething() {
 var a: String = "abc"
 
 var

    b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l2 = b?.length ?: -1 
 }
  45. if (originLocation != null) {
 if (originLocation.hierarchyInfo != null) {


    if (originLocation.hierarchyInfo.airport != null) {
 if (originLocation.hierarchyInfo.airport.airportCode != null) {
 departureAirportCode = originLocation.hierarchyInfo.airport.airportCode;
 }
 }
 
 }
 }
 else {
 departureAirportCode = "";
 }
  46. val departureAirportCode = originLocation?.hierarchyInfo?.airport?.airportCode ?: ""
 if (originLocation != null)

    {
 if (originLocation.hierarchyInfo != null) {
 if (originLocation.hierarchyInfo.airport != null) {
 if (originLocation.hierarchyInfo.airport.airportCode != null) {
 departureAirportCode = originLocation.hierarchyInfo.airport.airportCode;
 }
 }
 
 }
 }
 else {
 departureAirportCode = "";
 }
  47. The !! Operator fun doSomething() {
 var a: String =

    "abc"
 
 var b: String? = "abc"
 b = null // ok
 
 val l1 = a.length
 
 val l2 = b!!.length 
 }
  48. Optional-params //In Java void foo(int p1, boolean p2) { 


    }
 
 void foo(int p1) {
 foo(1, false);
 }
 
 void foo() {
 foo(1, false);
 }
  49. Data class data class Traveler(val name: String?, val age: Int)

    Automatically implements: equals()/hashCode()
 toString() of the form "User(name=John, age=42)",
 copy() function
  50. val testTravlerJohn = Traveler(“John”, 42) val testTravlerJane = Traveler(“Jane”, 41)

    assertEquals(testTravlerJohn, testTravlerJane) Data class in Testing
  51. public class Traveler(String name, Int age) @Override
 public boolean equals(Object

    o) {
 if (this == o) {
 return true;
 }
 if (!(o instanceof Traveler)) {
 return false;
 }
 
 Traveler traveler = (Traveler) o;
 
 if (name != name) {
 return false;
 }
 if (age != traveler.age) {
 return false;
 } return true; }
  52. Extension Functions //In Java public class StrUtils {
 public static

    String encodeString(String str) {
 return str.replaceAll(" ", "_")
 }
 } String text = "Hello World";
 System.out.println(StrUtils.encodeString(text)); 

  53. Extension Functions //In Kotlin fun String.encodeSpaces(): String {
 return this.replaceAll("

    ", "_")
 } val text = "hello world"
 
 println(text.encodeSpaces())
  54. val list = listOf("E", "H", "Hello", "Hi", "I")
 val map

    = mapOf(Pair("A", 1), Pair("B", 2), Pair("C", 3))
 
 list.forEach { s ->
 s.length
 } "E, H, Hello, Hi, I"
 
 Kotlin Collections Extensions
  55. val list = listOf("E", "H", "Hello", "Hi", "I")
 val map

    = mapOf(Pair("A", 1), Pair("B", 2), Pair("C", 3))
 
 var count = 0
 list.forEachIndexed { i, s ->
 count += i
 s.length
 } 
 "E, H, Hello, Hi, I"
 

  56. val list = listOf("E", "H", "Hello", "Hi", "I")
 val map

    = mapOf(Pair("A", 1), Pair("B", 2), Pair("C", 3))
 
 list.filter { s ->
 s.contains("H")
 }
 "H, Hello, Hi"
 

  57. val list = listOf("E", "H", "Hello", "Hi", "I")
 val map

    = mapOf(Pair("A", 1), Pair("B", 2), Pair("C", 3))
 
 list.first { s ->
 s.startsWith("He")
 }
 "Hello"
 

  58. val list = listOf("E", "H", "Hello", "Hi", "I")
 val map

    = mapOf(Pair("A", 1), Pair("B", 2), Pair("C", 3))
 
 map.forEach { entry ->
 entry.value }
 "A, B, C"
  59. //In Java final int[] sponsoredIndexes = { 0, 50, 51

    };
 
 ArrayList<Property> sponsored = new ArrayList<Property>();
 ListIterator<Property> it = properties.listIterator();
 while (it.hasNext()) {
 Property prop = it.next();
 if (prop.isSponsored()) {
 it.remove();
 sponsored.add(prop);
 }
 }
 
 for (int i = 0; i < sponsored.size() && i < sponsoredIndexes.length; i++) {
 if (sponsoredIndexes[i] <= properties.size()) {
 properties.add(sponsoredIndexes[i], sponsored.get(i));
 }
 }
  60. //In Kotlin fun putSponsoredItemsInCorrectPlaces(hotelList: List<Hotel>): List<Hotel> {
 val (sponsored, nonSponsored)

    = hotelList.partition { it.isSponsoredListing }
 val firstChunk = sponsored.take(1)
 val secondChunk = nonSponsored.take(49)
 val thirdChunk = sponsored.drop(1)
 val rest = nonSponsored.drop(49)
 return firstChunk + secondChunk + thirdChunk + rest
 }
  61. //In Java Observable.just("Hello World")
 .map(new Func1<String, Object>() {
 
 @Override


    public Object call(String s) {
 return s + "!";
 }
 })
 .subscribe(new Subscriber<String>() {
 @Override
 public void onCompleted() {
 //Completion
 }
 
 @Override
 public void onError(final Throwable e) {
 //TODO : Handle error here
 }
 
 @Override
 public void onNext(final String s) {
 Log.e("Output",s);
 }
 }); Reative Java
  62. Flow sensitive typing //In Java @Override
 public void onBindViewHolder(RecyclerView.ViewHolder holder,

    int position) {
 if (holder.getItemViewType() != LOADING_VIEW) {
 ((ViewHolder) holder).updateHotel();
 }
 else if (holder.getItemViewType() != HOTEL_VIEW) {
 ((LoadingViewHolder) holder).loadView();
 }
 }

  63. Flow sensitive typing //In Kotlin override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position:

    Int) {
 when (holder) {
 is HotelCellViewHolder-> holder.updateHotel()
 is LoadingViewHolder -> holder.loadView()
 }
 }
  64. Delegates var p: String by Delegate() Properties using the delegate

    expression will have its get() and set() methods delegated to the expression. * lazy * observable * notNull
  65. val view: Presenter by lazy {
 var view = stub.inflate()

    as Presenter
 view
 } Delegates.lazy
  66. Delegates.notNull class Foo {
 var bar : Bar by Delegates.notNull()

    // type is now Bar
 
 init {
 val s = bar // Using before setting throws an IllegalStateException!
 bar = Bar()
 }
 }
  67. Custom delegate(KotterKnife) fun <T : View> ViewGroup.bindView(id: Int): ReadOnlyProperty<Any, T>

    = ViewBinding(this, id) private class ViewBinding<T : View>(val source: Any, val id: Int) : ReadOnlyProperty<Any, T> {
 private val lazy = Lazy<T>()
 
 override fun getValue(thisRef: Any, property: KProperty<*>): T = lazy.get {
 findView<T>(source, id)
 ?: throw IllegalStateException("View ID $id for '${property.name}' not found.")
 }
 } val mapView: MapView by bindView(R.id.map_view)