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

DevFest 2019: Hyderabad - Using Kotlin for Andr...

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

DevFest 2019: Hyderabad - Using Kotlin for Android Dev: a 2-year-retrospective

A look back at 2 years of Kotlin development in Android. We’ll see how Kotlin helped us remove boilerplate, improve readability and how easy it is to adopt Kotlin as a Java developer.

Avatar for Kishore Babu

Kishore Babu

October 12, 2019

Other Decks in Technology

Transcript

  1. Agenda - Pros/Cons - Reduction of Code Boilerplate - Highlights

    - Language Features - Asynchronous Programming
  2. Transitioning from Java to Kotlin Pros: 1. Reduces a lot

    of boilerplate code 2. Compatible within existing Android Projects 3. Modern language features 4. Faster to compile on moderns JVMs 5. First Class Citizen status for Android SDK Cons: 1. Learning Curve 2. Best Practices - Work In Progress 3. Less developers available. 4. (Relatively) Smaller community
  3. Up to Speed: Kotlin Basics class Address { var name:

    String = "Holmes" var street: String = "Baker" var city: String = "London" var state: String? = null var zip: String = "123456" }
  4. Up to Speed: Kotlin Basics listOfInts.filter { it > 0

    } // this literal is of type '(it: Int) -> Boolean'
  5. Up to Speed: Extension Functions fun View?.isVisible(): Boolean = this?.visibility

    == View.VISIBLE txtView.isVisible() txtView.visibility == View.VISIBLE
  6. Null Safety - Safe Calls val a = "Kotlin" val

    b: String? = null println(b?.length)
  7. .apply{} val intent = Intent() intent.action = intentAction intent.data=Uri.parse(intentData) //Using

    apply function ( apply return this i.e Intent in this case) Intent() .apply { action = intentAction } .apply { data = Uri.parse(intentData)
  8. Objects object CarFactory { val cars = mutableListOf<Car>() fun makeCar(horsepowers:

    Int): Car { val car = Car(horsepowers) cars.add(car) return car } }
  9. • launch{} -> returns Job • async {} -> returns

    DeferedJob • runBlocking<Unit>{} -> returns explicitly given return type
  10. Coroutine builders and Scope: fun someViewModelFunction(){ GlobalScope.launch{ val someInt =

    longProcessingFunction() print(someInt.toString()) // will be printed later } println("end of viewmodel function") //will be printed first } suspend fun longTimeTakingFunction():Int{ repeat(100){ delay(100) //suspended function } return 10 }
  11. Custom scope and jobs: val job = SupervisorJob() val customScope:

    CoroutineScope = CoroutineScope(job + Dispatchers.Default) fun onDestroy() { job.cancel() // will cancel all child coroutines Or scope.cancel()//will cancel all the jobs started from this scope }
  12. Coroutine Context and Dispatchers : fun someViewModelFunction(){ GlobalScope.launch(Dispatchers.Default){ val someInt

    = longProcessingFunction() print(someInt.toString()) } doSomeOtherTask() } Dispatchers.IO -> For IO tasks Dispatchers.Default -> For computational tasks. Dispatchers.Main -> For UI tasks
  13. suspend fun getRandomNumber(): Int { delay(1000) return (0..10).random() } fun

    sum() { customScope.launch { val a = getRandomNumber() val b = getRandomNumber() print("${a + b}") //takes 2014 millis } }
  14. fun sum() { customScope.launch { val a = getRandomNumber() val

    b = getRandomNumber() print("${a + b}") //takes 2014 millis } } fun asyncSum() { customScope.launch { val a = async { getRandomNumber() } val b = async { getRandomNumber()} print("${a.await() + b.await()}") //takes 1014 millis } }
  15. fun getUserInfo() { try { viewModelScope.launch { throw IOException() }

    } catch (ex: Exception) { println("Exception occured") // will be called } }
  16. fun getUserInfo() { try { viewModelScope.async { throw IOException() }

    } catch (ex: Exception) { println("Exception occured") // will never be called } }
  17. fun getUserInfo() { try { viewModelScope.async { throw IOException() }.await()

    } catch (ex: Exception) { println("Exception occured") // will be called } }
  18. Exception thrown by child job try { viewModelScope.launch { try

    { launch { throw IOException() } } catch (ex: Exception) { println("Exception Child job")// control will never reach here } } } catch (ex: Exception) { println("Exception Parent job")// will always be called }
  19. Exception thrown by child job try { viewModelScope.launch { try

    { async { //relying on user to await() throw IOException() } } catch (ex: Exception) { println("Exception Child job")// control will never reach here } } } catch (ex: Exception) { println("Exception Parent job")// will always be called }
  20. Exception thrown by child job try { viewModelScope.launch { try

    { val deferedJob = async { throw IOException() } deferedJob.await() } catch (ex: Exception) { println("Exception Child job") // called first } } } catch (ex: Exception) { println("Exception Parent job") // called later }
  21. CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, throwable -> println("Exception

    occurred $throwable") } viewModelScope.launch(handler) { throw Exception("This exception will be printed") } viewModelScope.async(handler) { throw Exception("This exception will not be printed") }
  22. Wrapping Up • All new projects are Kotlin, by default.

    • Most recent projects are using Coroutines