Slide 1

Slide 1 text

fun() Talk Exploring Kotlin Functions @n8ebel

Slide 2

Slide 2 text

♥ == Kotlin + Functions @n8ebel #androidsummit 2

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Easy to Get Started @n8ebel #androidsummit 6

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

From Java to Kotlin @n8ebel #androidsummit 8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

Flexible & Convenient @n8ebel #androidsummit 13

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

Parameter Basics @n8ebel #androidsummit 16

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Default Parameters @n8ebel #androidsummit 19

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

@n8ebel #androidsummit 27

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Named Arguments @n8ebel #androidsummit 29

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Variable Arguments @n8ebel #androidsummit 37

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Return Types @n8ebel #androidsummit 46

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Generic Functions @n8ebel #androidsummit 51

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

@n8ebel #androidsummit 53

Slide 54

Slide 54 text

Variations In Scope @n8ebel #androidsummit 54

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Top-Level functions @n8ebel #androidsummit 56

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

Member Functions @n8ebel #androidsummit 66

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

Local Functions @n8ebel #androidsummit 70

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

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

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

Companion Objects @n8ebel #androidsummit 78

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

Variations @n8ebel #androidsummit 90

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

infix Functions @n8ebel #androidsummit 92

Slide 93

Slide 93 text

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

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

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

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

Extension Functions @n8ebel #androidsummit 99

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

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

Slide 105

Slide 105 text

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

Slide 106

Slide 106 text

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

Slide 107

Slide 107 text

@n8ebel #androidsummit 107

Slide 108

Slide 108 text

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

Slide 109

Slide 109 text

Higher-Order Functions @n8ebel #androidsummit 109

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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

Slide 112

Slide 112 text

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

Slide 113

Slide 113 text

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

Slide 114

Slide 114 text

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

Slide 115

Slide 115 text

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

Slide 116

Slide 116 text

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

Slide 117

Slide 117 text

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

Slide 118

Slide 118 text

inline Functions @n8ebel #androidsummit 118

Slide 119

Slide 119 text

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

Slide 120

Slide 120 text

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

Slide 121

Slide 121 text

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

Slide 122

Slide 122 text

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

Slide 123

Slide 123 text

Android Reimagined @n8ebel #androidsummit 123

Slide 124

Slide 124 text

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

Slide 125

Slide 125 text

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

Slide 126

Slide 126 text

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

Slide 127

Slide 127 text

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

Slide 128

Slide 128 text

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

Slide 129

Slide 129 text

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

Slide 130

Slide 130 text

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

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

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

Slide 133

Slide 133 text

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

Slide 134

Slide 134 text

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

Slide 135

Slide 135 text

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

Slide 136

Slide 136 text

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

Slide 137

Slide 137 text

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

Slide 138

Slide 138 text

Thanks For Coming @n8ebel #androidsummit 138