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

fun Talk(): Exploring Kotlin Functions

Nate Ebel
August 16, 2018

fun Talk(): Exploring Kotlin Functions

Nate Ebel

August 16, 2018
Tweet

More Decks by Nate Ebel

Other Decks in Programming

Transcript

  1. fun() Talk
    Exploring Kotlin Functions
    @n8ebel

    View Slide


  2. == Kotlin + Functions
    @n8ebel #androidsummit 2

    View Slide


  3. == Kotlin + Functions
    4 Free functions
    4 Higher-order functions
    4 Rich stdlib
    @n8ebel #androidsummit 3

    View Slide


  4. == Kotlin + Functions
    4 arrayOf(), listOf()
    4 measureTimeMillis { doSomething() }
    4 orEmpty()
    4 forEach(), groupBy()
    @n8ebel #androidsummit 4

    View Slide

  5. Let's Have Some fun()
    Functions in Kotlin:
    - Easy to get started
    - Flexible & Convenient
    - Enable Freedom to Reimagine
    @n8ebel #androidsummit 5

    View Slide

  6. Easy to Get Started
    @n8ebel #androidsummit 6

    View Slide

  7. Easy to Get Started
    4 Can use the IDE conversion tool
    4 Can try online (https://try.kotlinlang.org)
    4 Easy to transfer existing knowledge
    @n8ebel #androidsummit 7

    View Slide

  8. From Java to Kotlin
    @n8ebel #androidsummit 8

    View Slide

  9. Hello Java Method
    class Greeter {
    void helloFunctions() {
    System.out.println("Yay, Functions");
    }
    }
    4 return type, name, method body
    @n8ebel #androidsummit 9

    View Slide

  10. Java Method Converted to Kotlin
    class Greeter {
    fun helloFunctions() {
    println("Yay, Functions")
    }
    }
    4 adds the fun keyword
    4 no explicit return type
    @n8ebel #androidsummit 10

    View Slide

  11. Further Simplification
    class Greeter {
    fun helloFunctions() = println("Yay, Functions")
    }
    @n8ebel #androidsummit 11

    View Slide

  12. Further Simplification
    fun helloFunctions() = println("Yay, Functions")
    @n8ebel #androidsummit 12

    View Slide

  13. Flexible & Convenient
    @n8ebel #androidsummit 13

    View Slide

  14. Flexible & Convenient
    4 Parameter & type flexibility
    4 Variations in scoping
    4 Variety of modifiers
    @n8ebel #androidsummit 14

    View Slide

  15. Parameter & Type Freedom
    4 Default parameters
    4 Named arguments
    4 Variable arguments
    4 Inferred return types
    4 Generic functions
    @n8ebel #androidsummit 15

    View Slide

  16. Parameter Basics
    @n8ebel #androidsummit 16

    View Slide

  17. Parameter Basics
    fun helloFunctions(excitingThing:String) {
    println("Yay, " + excitingThing)
    }
    helloFunctions("functions")
    // outputs "Yay, functions"
    @n8ebel #androidsummit 17

    View Slide

  18. Parameter Basics
    fun helloFunctions(exclamation:String, excitingThing:String) {
    println(exclamation + ", " + excitingThing)
    }
    helloFunctions("Yay", "functions")
    // outputs "Yay, functions"
    @n8ebel #androidsummit 18

    View Slide

  19. Default Parameters
    @n8ebel #androidsummit 19

    View Slide

  20. Default Parameters
    fun helloFunctions(exclamation:String, excitingThing:String = "functions") {
    println(exclamation + ", " + excitingThing)
    }
    // outputs "Yay, functions"
    helloFunctions("Yay", "functions")
    // outputs "Yay, functions"
    helloFunctions("Yay")
    @n8ebel #androidsummit 20

    View Slide

  21. Default Parameters
    4 function parameters can have default values
    4 when an argument is omitted, the default value is
    used
    @n8ebel #androidsummit 21

    View Slide

  22. Default Parameters
    4 allows us the flexibility of overloads without the
    verbosity of writing them
    4 help document the function contract by indicating
    what "sensible defaults" might be
    @n8ebel #androidsummit 22

    View Slide

  23. Default Parameters & Java
    4 Java doesn't have default parameter values
    4 must specify all parameter values when calling from
    Java
    @n8ebel #androidsummit 23

    View Slide

  24. Default Parameters & Java
    public class Main {
    // compiles
    GreetingFunctionsKt.helloFunctions("Yay", "functions");
    // does not compile
    GreetingFunctionsKt.helloFunctions("Yay");
    }
    @n8ebel #androidsummit 24

    View Slide

  25. Default Parameters & Java
    4 can use @JvmOverloads to generate overloads for
    each parameter
    4 generated overloads will use the specified default
    values
    @n8ebel #androidsummit 25

    View Slide

  26. Default Parameters & @JvmOverloads
    @JvmOverloads
    fun helloFunctions(exclamation:String, excitingThing:String = "functions") {
    println(exclamation + ", " + excitingThing)
    }
    @n8ebel #androidsummit 26

    View Slide

  27. @n8ebel #androidsummit 27

    View Slide

  28. Default Parameters & @JvmOverloads
    With the generated Java methods now available, both
    Java invocations now compile
    public class Main {
    GreetingFunctionsKt.helloFunctions("Yay", "functions");
    GreetingFunctionsKt.helloFunctions("Yay");
    }
    @n8ebel #androidsummit 28

    View Slide

  29. Named Arguments
    @n8ebel #androidsummit 29

    View Slide

  30. Named Arguments
    helloFunctions("functions", "functions")
    4 How do we know which value is correct?
    @n8ebel #androidsummit 30

    View Slide

  31. Named Arguments
    helloFunctions(exclamation = "yay!", excitingThing = "functions")
    4 Much easier to understand with named arguments
    @n8ebel #androidsummit 31

    View Slide

  32. Named Arguments
    4 Improve readability of function invocations
    4 Modify order of passed parameters by using named
    arguments
    4 Refactor parameter count/order without breaking
    code
    @n8ebel #androidsummit 32

    View Slide

  33. Named Arguments
    fun helloFunctions(exclamation:String, excitingThing:String = "functions") {
    println(exclamation + ", " + excitingThing)
    }
    helloFunctions("Hooray", "functions")
    helloFunctions("Hooray")
    helloFunctions(excitingThing = "functions", exclamation = "Hooray")
    // all output "Hooray, functions"
    @n8ebel #androidsummit 33

    View Slide

  34. Named Argument Limitations
    4 there are limitations to how named & positioned
    arguments are used
    4 once an argument name is specified, all subsequent
    arguments must be named as well
    @n8ebel #androidsummit 34

    View Slide

  35. Named Argument Limitations
    helloFunctions("hooray", "Android Summit")
    helloFunctions("hooray", excitingThing = "Android Summit")
    // both output "hooray, Android Summit"
    helloFunctions(excitingThing = "Android Summit", "hooray")
    // error: Mixing named and positioned arguments not allowed
    @n8ebel #androidsummit 35

    View Slide

  36. Named Arguments & Java
    4 Named arguments are not supported from Java
    4 Arguments must be passed in the order they are
    defined
    @n8ebel #androidsummit 36

    View Slide

  37. Variable Arguments
    @n8ebel #androidsummit 37

    View Slide

  38. Variable Number of Arguments
    We can define a parameter to accept a variable number
    of arguments T
    - use the vararg keyword
    - vararg param is then treated as an array of type T
    - default value must now be an array
    @n8ebel #androidsummit 38

    View Slide

  39. Variable Number of Arguments
    fun helloFunctions(exclamation:String, vararg excitingThings:String) {
    for(excitingThing in excitingThings) {
    println(exclamation + ", " + excitingThing)
    }
    }
    helloFunctions("yay!", "Android Summit", "Kotlin", "Android")
    // outputs:
    // yay!, Android Summit
    // yay!, Kotlin
    // yay!, Android
    @n8ebel #androidsummit 39

    View Slide

  40. Variable Number of Arguments
    Typically, a vararg parameter will be the last one
    Can be used in any order if:
    - other params are called using named argument syntax
    - last param is a function passed outside the
    parentheses
    @n8ebel #androidsummit 40

    View Slide

  41. Variable Number of Arguments
    This works
    helloFunctions("yay!", "Android Summit", "Kotlin", "Android")
    helloFunctions("Android Summit", "Kotlin", "Android", exclamation = "yay!")
    // both output:
    // yay!, Android Summit
    // yay!, Kotlin
    // yay!, Android
    @n8ebel #androidsummit 41

    View Slide

  42. Variable Number of Arguments
    This works
    helloFunctions("Android Summit", "Kotlin", "Android")
    // output:
    // "Android Summit, Kotlin"
    // "Android Summit, Android"
    @n8ebel #androidsummit 42

    View Slide

  43. Variable Number of Arguments
    This won't compile
    helloFunctions("Android Summit", exclamation = "yay!", "Kotlin", "Android")
    // error: "no matching function"
    @n8ebel #androidsummit 43

    View Slide

  44. Variable Number of Arguments
    Use "spread" operator to pass an existing array of
    values
    val thingsToBeExcitedAbout = arrayOf("Android Summit", "Kotlin", "Android")
    helloFunctions("yay!", *thingsToBeExcitedAbout)
    // output:
    // yay!, Android Summit
    // yay!, Kotlin
    // yay!, Android
    @n8ebel #androidsummit 44

    View Slide

  45. Variable Number of Arguments
    helloFunctions("yay!", "coffee", *thingsToBeExcitedAbout)
    helloFunctions("yay!", *thingsToBeExcitedAbout, "coffee")
    4 "Spreading" can be used alone, or with other passed
    varargs as well
    4 input array to the vararg parameter is handled in
    order
    @n8ebel #androidsummit 45

    View Slide

  46. Return Types
    @n8ebel #androidsummit 46

    View Slide

  47. Return Types
    What is the return type?
    fun helloFunctions(exclamation:String, excitingThing:String="functions") {
    println(exclamation + ", " + excitingThing)
    }
    4 If a function does not return any useful value, i
    ts
    return type is Unit
    @n8ebel #androidsummit 47

    View Slide

  48. Return Types
    These are equivalent
    fun helloFunctions(exclamation:String, excitingThing:String="functions") : Unit {
    println(exclamation + ", " + excitingThing)
    }
    fun helloFunctions(exclamation:String, excitingThing:String="functions") {
    println(exclamation + ", " + excitingThing)
    }
    @n8ebel #androidsummit 48

    View Slide

  49. Return Types: Non-Unit Type
    Functions with a block body require explicit return type
    & call for non-Unit functions
    fun helloFunctions(exclamation:String, excitingThing:String="functions") : String {
    return exclamation + ", " + excitingThing
    }
    @n8ebel #androidsummit 49

    View Slide

  50. Return Types: Non-Unit Type
    Can infer return type for single-expression functions
    fun helloFunctions(exclamation:String, excitingThing:String="functions")
    = exclamation + ", " + excitingThing
    @n8ebel #androidsummit 50

    View Slide

  51. Generic Functions
    @n8ebel #androidsummit 51

    View Slide

  52. Generic Functions
    4 Like classes, functions may have generic type
    parameters
    4 many stdlib functions are built with generics
    @n8ebel #androidsummit 52

    View Slide

  53. @n8ebel #androidsummit 53

    View Slide

  54. Variations In Scope
    @n8ebel #androidsummit 54

    View Slide

  55. Variations In Scope
    4 Top-level
    4 Member functions
    4 Local
    4 CompanionObject
    4 Extension functions
    @n8ebel #androidsummit 55

    View Slide

  56. Top-Level functions
    @n8ebel #androidsummit 56

    View Slide

  57. Top-Level functions
    4 Not associated with a class or object
    4 Defined within a Kotlin file
    4 Belong to their declared file's package
    4 Import to use within other packages
    @n8ebel #androidsummit 57

    View Slide

  58. Top-Level Function Patterns
    4 Replace stateless classes filled with static methods
    4 Swap your "Util" or "Helper" classes with functions
    @n8ebel #androidsummit 58

    View Slide

  59. Top-Level Function Considerations
    4 Not truly removing classes
    4 Generated as a public static method on a class using
    a special convention
    4 Kt.java
    @n8ebel #androidsummit 59

    View Slide

  60. Top-Level Function Considerations
    // inside Logging.kt
    package logging
    fun log(error:Throwable) {...}
    @n8ebel #androidsummit 60

    View Slide

  61. Top-Level Function Considerations
    Generated Code
    public class LoggingKt {
    public static void log(Throwable error) {...}
    }
    @n8ebel #androidsummit 61

    View Slide

  62. Top-Level Function Considerations
    // call from Kotlin
    log(Throwable("oops"))
    // call from Java
    LoggingKt.log(new Throwable("oops"))
    @n8ebel #androidsummit 62

    View Slide

  63. Top-Level Function Considerations
    Can override the generated class/file name
    4 Add @file:JvmName() to
    function's file
    4 Must be before the declared package
    @n8ebel #androidsummit 63

    View Slide

  64. Top-Level Function Considerations
    // inside Logging.kt
    @file:JvmName("LoggingFunctions")
    package logging
    fun log(error:Throwable) {...}
    @n8ebel #androidsummit 64

    View Slide

  65. Top-Level Function Considerations
    // call from Kotlin
    log(Throwable("oops"))
    // call from Java
    LoggingFunctions.log(new Throwable("oops"))
    @n8ebel #androidsummit 65

    View Slide

  66. Member Functions
    @n8ebel #androidsummit 66

    View Slide

  67. Member Functions
    4 Function associated with a class or object
    4 Have access to private members of the class or object
    @n8ebel #androidsummit 67

    View Slide

  68. Member Functions
    class Speaker() {
    fun giveTalk() { ... }
    }
    // create instance of class Speaker and call giveTalk()
    Speaker().giveTalk()
    @n8ebel #androidsummit 68

    View Slide

  69. Member Function Considerations
    4 Default arguments can't be changed in overridden
    methods
    4 If overriding a method, you must omit the default
    values
    @n8ebel #androidsummit 69

    View Slide

  70. Local Functions
    @n8ebel #androidsummit 70

    View Slide

  71. Local Functions
    Functions inside of functions
    4 Create a function that is scoped to another function
    4 Useful if your function is only ever called from
    another function
    @n8ebel #androidsummit 71

    View Slide

  72. Local Functions
    4 Declare like any other function, but within an
    existing function
    4 Have access to all params and variables of the
    enclosing function
    @n8ebel #androidsummit 72

    View Slide

  73. Local Functions
    fun outerFunction(name:String) {
    fun innerFunction() {
    println(name)
    }
    ...
    innerFunction() // will print the passed name
    }
    @n8ebel #androidsummit 73

    View Slide

  74. Local Functions
    Why would you want this?
    4 Clean code
    4 Avoids code duplication
    4 Avoid deep chains of function calls
    @n8ebel #androidsummit 74

    View Slide

  75. Local Functions
    fun parseAccount(response:AccountResponse) : Account {
    ...
    val hobbies = response.getField("hobbies").map{
    val key = it.getField("key")
    Hobby(key)
    }
    val favoriteFoods = response.getField("favorite_foods").map{
    val key = it.getField("key")
    Food(key)
    }
    }
    @n8ebel #androidsummit 75

    View Slide

  76. Local Functions
    fun parseAccount(response:AccountResponse) : Account {
    fun parseKey(entity:ResponseEntity) = entity.getField("key")
    ...
    val hobbies = response.getField("hobbies").map{
    val key = parseKey(it)
    Hobby(key)
    }
    val favoriteFoods = response.getField("favorite_foods").map{
    val key = parseKey(it)
    Food(key)
    }
    }
    @n8ebel #androidsummit 76

    View Slide

  77. Local Function Considerations
    4 Local function or private method?
    4 Is the logic going to be needed outside the current
    function?
    4 Does the logic need to be tested in isolation?
    4 Is the enclosing function still readable?
    @n8ebel #androidsummit 77

    View Slide

  78. Companion Objects
    @n8ebel #androidsummit 78

    View Slide

  79. Companion Objects
    4 No static method/functions in Kotlin
    4 Recommended to use top-level functions instead
    4 What if you need access to private members of an
    object?
    @n8ebel #androidsummit 79

    View Slide

  80. Companion Objects
    4 Want to create a factory method?
    4 Define a member function on a companion object to
    gain access to private members/constructors
    @n8ebel #androidsummit 80

    View Slide

  81. Companion Objects: Use from Kotlin
    class Course private constructor(val key:String)
    // won't work
    // can't access the private constructor
    fun createCourse(key:String) : Course {
    return Course(key)
    }
    @n8ebel #androidsummit 81

    View Slide

  82. Companion Objects: Use from Kotlin
    class Course private constructor(val key:String) {
    companion object {
    fun createCourse(key:String) : Course {
    return Course(key)
    }
    }
    }
    @n8ebel #androidsummit 82

    View Slide

  83. Companion Objects: Use from Kotlin
    class Course private constructor(val key:String) {
    companion object {
    fun createCourse(key:String) : Course {
    return Course(key)
    }
    }
    }
    // can then call the factory method
    Course.createCourse("somekey")
    @n8ebel #androidsummit 83

    View Slide

  84. Companion Objects: Use From Java
    class AuthFragment : Fragment() {
    ...
    companion object {
    fun newInstance(username: String) = ...
    }
    }
    @n8ebel #androidsummit 84

    View Slide

  85. Companion Objects: Use From Java
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // explicitly reference `Companion` from Java
    AuthFragment.Companion.newInstance("username")
    }
    @n8ebel #androidsummit 85

    View Slide

  86. Companion Objects: Renaming
    Usage from Java is verbose
    AuthFragment.Companion.newInstance("username")
    @n8ebel #androidsummit 86

    View Slide

  87. Companion Objects: Renaming
    class AuthFragment : Fragment() {
    ...
    companion object Factory {
    fun newInstance(username: String) = ...
    }
    }
    AuthFragment.Factory.newInstance("username")
    @n8ebel #androidsummit 87

    View Slide

  88. Companion Objects: @JvmStatic
    class AuthFragment : Fragment() {
    ...
    companion object {
    @JvmStatic
    fun newInstance(username: String) = ...
    }
    }
    @n8ebel #androidsummit 88

    View Slide

  89. Companion Objects: @JvmStatic
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // no need to reference `Companion`
    AuthFragment.newInstance("username")
    }
    @n8ebel #androidsummit 89

    View Slide

  90. Variations
    @n8ebel #androidsummit 90

    View Slide

  91. Variations
    4 infix
    4 extension
    4 higher-order
    4 inline
    @n8ebel #androidsummit 91

    View Slide

  92. infix Functions
    @n8ebel #androidsummit 92

    View Slide

  93. infix Functions
    4 infix keyword enables usage of infix notation
    4 What is infix notation?
    4 Can omit the dot & parentheses for a function call
    4 "key" to "value"
    @n8ebel #androidsummit 93

    View Slide

  94. infix Functions
    4 Must be a member function or extension function
    4 Must take a single, non-varargs, parameter with no
    default value
    @n8ebel #androidsummit 94

    View Slide

  95. infix Functions
    class ConferenceAttendee {
    infix fun addInterest(name:String){...}
    }
    // call the function without dot or parentheses
    val attendee = ConferenceAttendee()
    attendee.addInterest("Kotlin")
    attendee addInterest "Kotlin"
    @n8ebel #androidsummit 95

    View Slide

  96. infix Functions
    4 Provides a very clean, human-readable syntax
    4 Core building block of custom DSLs
    @n8ebel #androidsummit 96

    View Slide

  97. infix Functions: stdlib
    for (i in 0 until 10 step 2) {
    println(i) // prints 0,2,4,6,8
    }
    "key" to someValue // creates a Pair
    var result: Boolean
    result = true or false // perform logical operations
    result = true and false
    @n8ebel #androidsummit 97

    View Slide

  98. infix Functions: Kotlin Test
    "hello" should haveSubstring("ell")
    "hello" shouldNot haveSubstring("olleh")
    https://github.com/kotlintest/kotlintest
    @n8ebel #androidsummit 98

    View Slide

  99. Extension Functions
    @n8ebel #androidsummit 99

    View Slide

  100. Extension Functions
    4 Extend the functionality of an existing class
    4 Defined outside the class
    4 Used as if they were a member of a class
    @n8ebel #androidsummit 100

    View Slide

  101. Why Extension Functions?
    4 Clean-up or extend classes & apis you don't control
    4 Remove helper classes & simplify top-level functions
    @n8ebel #androidsummit 101

    View Slide

  102. Extension Functions
    // add a new function to the View class
    fun View.isVisible() = visibility == View.VISIBLE
    yourView.isVisible()
    @n8ebel #androidsummit 102

    View Slide

  103. Extension Functions
    fun showToast(
    context: Context,
    msg:String,
    duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, msg, duration).show()
    }
    showToast(context, "Toast!")
    @n8ebel #androidsummit 103

    View Slide

  104. Extension Functions
    fun Context.showToast(
    msg: CharSequence,
    duration: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(this, msg, duration).show()
    }
    context.showToast("Toast!")
    @n8ebel #androidsummit 104

    View Slide

  105. Extension Function Considerations
    4 How are these generated under the hood?
    4 How are these called from Java?
    @n8ebel #androidsummit 105

    View Slide

  106. Extension Function Considerations
    4 Generated as static methods that accept the
    receiver object as it's first argument
    4 Default behavior is to use
    Kt.
    @n8ebel #androidsummit 106

    View Slide

  107. @n8ebel #androidsummit 107

    View Slide

  108. Extension Function Considerations
    // ContextExtensions.kt
    fun Context.showToast(...) { ... }
    // when called from Java
    ContextExtensionsKt.showToast(context, "Toast!");
    @n8ebel #androidsummit 108

    View Slide

  109. Higher-Order Functions
    @n8ebel #androidsummit 109

    View Slide

  110. Higher-Order Functions
    4 Functions that take, or return, other functions
    4 Can be lambda or function reference
    4 Many examples in the Kotlin standard library apply,
    also, run
    @n8ebel #androidsummit 110

    View Slide

  111. Higher-Order Functions
    4 Enable interesting patterns & conventions
    4 Support functional programming
    4 Can cleanup setup/teardown patterns such as
    shared prefs
    @n8ebel #androidsummit 111

    View Slide

  112. Higher-Order Functions
    fun getScoreCalculator(level:Level) {
    return when (level) {
    Level.EASY -> { state:ScoreState -> state.score * 10 }
    Level.HARD -> { state:ScoreState -> state.score * 5 * state.accuracy }
    }
    }
    @n8ebel #androidsummit 112

    View Slide

  113. Higher-Order Functions
    val predicate = { number:Int -> number > 5 }
    listOf(2,4,6,8).filter(predicate)
    @n8ebel #androidsummit 113

    View Slide

  114. Higher-Order Functions
    fun filterTheList(value:Int) = value > 5
    listOf(2,4,6,8).filter(::filterTheList)
    @n8ebel #androidsummit 114

    View Slide

  115. Higher-Order Functions
    If the last parameter of a function is a function, you
    can omit the parentheses
    listOf(2,4,6,8).filter{ number -> number > 5 }
    @n8ebel #androidsummit 115

    View Slide

  116. Higher-Order Functions
    public inline fun synchronized(lock: Any, block: () -> R): R {
    monitorEnter(lock)
    try {
    return block()
    }
    finally {
    monitorExit(lock)
    }
    }
    // call from Kotlin
    synchronized(database) {
    database.prePopulate()
    }
    @n8ebel #androidsummit 116

    View Slide

  117. Higher-Order Function Performance
    "Using higher-order functions imposes certain
    runtime penalties"
    4 Extra class created when using lambda
    4 If lambda captures variables, extra object created on
    each call
    @n8ebel #androidsummit 117

    View Slide

  118. inline Functions
    @n8ebel #androidsummit 118

    View Slide

  119. inline Functions
    4 Helps solve higher-order function performance hits
    4 Body of the inlined function is substituted for
    invocations of the function
    @n8ebel #androidsummit 119

    View Slide

  120. inline Functions
    inline fun synchronized(lock: Lock, action: () -> T): T {
    lock.lock()
    try {
    return action()
    }
    finally {
    lock.unlock()
    }
    }
    // call from Kotlin
    synchronized(Lock()) {...}
    @n8ebel #androidsummit 120

    View Slide

  121. inline Functions
    // sample usage
    fun inlineExample(l:Lock) {
    println("before")
    synchronized(l) {
    println("action")
    }
    println("after")
    }
    @n8ebel #androidsummit 121

    View Slide

  122. inline Functions
    With inline the generated code is equivalent to this
    // resulting code
    fun inlineExample(l:Lock) {
    println("before")
    lock.lock()
    try {
    println("action")
    }
    finally {
    lock.unlock()
    }
    println("after")
    }
    @n8ebel #androidsummit 122

    View Slide

  123. Android Reimagined
    @n8ebel #androidsummit 123

    View Slide

  124. Fewer Helper Classes
    4 ContextHelper, ViewUtils
    4 Replace with
    4 top-level functions
    4 extension functions
    @n8ebel #androidsummit 124

    View Slide

  125. Less Boilerplate
    fun doTheThingSafely(theThing:() -> Unit) {
    try {
    theThing()
    } catch(error:Throwable) {
    // handle error
    }
    }
    doTheThingSafely { unsafeFunction() }
    @n8ebel #androidsummit 125

    View Slide

  126. Upgrade Our Apis
    Can use extensions, default params, etc to cleanup/
    simplify/extend common apis
    4 Now seeing community supported examples of this
    4 Android KTX: https://github.com/android/android-
    ktx
    4 Anko: https://github.com/Kotlin/anko
    @n8ebel #androidsummit 126

    View Slide

  127. Android KTX
    sharedPreferences.edit()
    .putString("key", "without KTX")
    .putBoolean("isLessBoilerplate", false)
    .apply()
    sharedPreferences.edit {
    putString("key", "with KTX")
    putBoolean("isLessBoilerplate", true)
    }
    @n8ebel #androidsummit 127

    View Slide

  128. Android KTX
    // without KTX
    supportFragmentManager.beginTransaction()
    .replace(R.id.fragmentContainer, SomeFragment())
    .addToBackStack("name")
    .commit()
    // with KTX
    supportFragmentManager.transaction {
    replace(R.id.fagmentContainer, SomeFragment())
    addToBackStack("name")
    }
    @n8ebel #androidsummit 128

    View Slide

  129. Cleaner Syntax
    fun log(msg:String) {...}
    inline fun runOnBackgroundThread(action:() -> Unit) { ... }
    4 More fluent syntax
    4 Simplify test mocking
    4 Avoids extra classes
    @n8ebel #androidsummit 129

    View Slide

  130. Useful Collection Functions
    4 orEmpty()
    4 arrayOf(), listOf(), mapOf()
    4 associateBy(), groupBy()
    4 map(), mapIndexed()
    4 reduce(), sum(), filter(), partition()
    @n8ebel #androidsummit 130

    View Slide

  131. Useful Collection Functions
    // easily calculate sum from collection
    val totalDownloadSize = downloadRecords.sumBy { it.downloadSize }
    // sort all DownloadRecords based on download time
    val sortedDownloadEntities = downloadRecords.sortedByDescending { record ->
    record.downloadTime
    }
    @n8ebel #androidsummit 131

    View Slide

  132. Useful Collection Functions
    // return map with all DownloadRecords mapped to their parent enrollmentKey
    val entitiesGroupedByEnrollmentKey = downloadRecords.groupBy { record ->
    record.enrollmentKey
    }
    // ensure we have a non-null collection and map all records to view models
    val viewModels = inputRecords.orEmpty().map { record ->
    createViewModel(record)
    }
    @n8ebel #androidsummit 132

    View Slide

  133. Useful String Functions
    4 isEmpty(), isNotEmpty()
    4 substringBefore(), substringAfter()
    4 orEmpty()
    @n8ebel #androidsummit 133

    View Slide

  134. Useful String Functions
    if(!url.isNullOrEmpty()) {
    loadData(url)
    }
    viewModel.body = model.description.orEmpty()
    @n8ebel #androidsummit 134

    View Slide

  135. Kotlin functions provide
    flexibility & freedom in
    how you build your apps
    @n8ebel #androidsummit 135

    View Slide

  136. Go, and Have fun()
    4 Easy to get started with functions
    4 Flexibility gives convenience
    4 Enables us to reimagine how we build our apps
    @n8ebel #androidsummit 136

    View Slide

  137. Let's Continue the Discussion
    with("n8ebel").apply {
    Twitter
    YouTube
    .com
    Medium
    Facebook
    GitHub
    }
    @n8ebel #androidsummit 137

    View Slide

  138. Thanks For Coming
    @n8ebel #androidsummit 138

    View Slide