Slide 1

Slide 1 text

KOTLIN EXTENSIONS AND HIGHER ORDER FUNCTIONS JITIN SHARMA

Slide 2

Slide 2 text

WHAT ARE EXTENSION FUNCTIONS ▸ Extensions are functions which can be added to existing classes(not really) ▸ Black magic == Static functions ▸ Less power than member functions ▸ They are meant to remove Utils like classes.

Slide 3

Slide 3 text

fun Double.toFahrenheit() : Double = (this * 1.8) + 32 val f = 34.toFahrenheit() //call like this fun Boolean.toString() : String = "abc" true.toString() //"true"

Slide 4

Slide 4 text

fun Double.toFahrenheit() : Double = (this * 1.8) + 32 val f = 34.toFahrenheit() //call like this fun Boolean.toString() : String = "abc" true.toString() //"true"

Slide 5

Slide 5 text

HIGHER ORDER FUNCTIONS ▸ Hail lambdas ▸ Functionception - Function as a parameter of function and returning a function ▸ Functions can be passed around as objects ▸ Bonus Point: SAM conversions for Java Interfaces

Slide 6

Slide 6 text

HOW TO

Slide 7

Slide 7 text

KOTLIN 101 - REMOVE THEM NULL CHECKS ▸ if (someObject != null) { } ▸ someObject?.let { it-> }

Slide 8

Slide 8 text

WORK WITH `APPLY`! supportActionBar?.apply { setDisplayHomeAsUpEnabled(true) setDisplayShowHomeEnabled(true) } // Use apply to avoid repetition of calling variable // Combine with and apply

Slide 9

Slide 9 text

WORK WITH `APPLY`! supportActionBar?.apply { setDisplayHomeAsUpEnabled(true) setDisplayShowHomeEnabled(true) } fun addTintWithCompat(drawable: Drawable, colorInt: Int): Drawable { return with(drawable) { DrawableCompat.wrap(drawable).apply { DrawableCompat.setTint(this, colorInt) } } } // Use apply to avoid repetition of calling variable // Combine with and apply

Slide 10

Slide 10 text

WORK `WITH` APPLY! // Insert functional programming here :) fun movieListReducer(action: Action, movieListState: MovieListState?): MovieListState { return with(movieListState) { val state = movieListState ?: MovieListState() when (action) { is displayMovies -> { state.copy(movieObjects = action.movieObjects) } else -> state } } }

Slide 11

Slide 11 text

KOTLIN LIBRARIES

Slide 12

Slide 12 text

KOTLIN LIBRARIES

Slide 13

Slide 13 text

KOTLIN LIBRARIES

Slide 14

Slide 14 text

CODE VISIBILITY FOOTPRINT ▸ Koltin can help in reducing visible code by wrapping around functions. ▸ You can move away functions which are not important from visibility point of view.

Slide 15

Slide 15 text

DO IT EFFICIENTLY

Slide 16

Slide 16 text

DO IT EFFICIENTLY Move away methods

Slide 17

Slide 17 text

DIY

Slide 18

Slide 18 text

DO IT YOURSELF // interface for item click // initialize interface // setting interface method on click // getting on click in main class JAVA WAY

Slide 19

Slide 19 text

DO IT YOURSELF // Add a function in parameter of adapter constructor // Invoke listener inside on click // Access listener as lambda in main class KOTLIN WAY

Slide 20

Slide 20 text

inline fun justTry(block: () -> T) = try { block() } catch (_: Throwable) { // log here } GENERAL FUNCTIONALITIES

Slide 21

Slide 21 text

inline fun justTry(block: () -> T) = try { block() } catch (_: Throwable) { // log here } GENERAL FUNCTIONALITIES fun String.toIntOrZero() : Int { var value = 0 justTry { value = this.toInt() } return value }

Slide 22

Slide 22 text

inline fun debugMode(block : () -> Unit) { if (BuildConfig.DEBUG) { block() } }

Slide 23

Slide 23 text

debugMode { StrictMode .setThreadPolicy(StrictMode.ThreadPolicy.Builder() .detectAll() .penaltyLog() .build()) } inline fun debugMode(block : () -> Unit) { if (BuildConfig.DEBUG) { block() } }

Slide 24

Slide 24 text

GOT INTERNET? if (isNetworkStatusAvailable()) { val apiService = ApiClient.client?.create(ApiInterface::class.java) val call = apiService?.discoverMovies(API_KEY) call?.enqueue(this) }

Slide 25

Slide 25 text

GOT INTERNET? if (isNetworkStatusAvailable()) { val apiService = ApiClient.client?.create(ApiInterface::class.java) val call = apiService?.discoverMovies(API_KEY) call?.enqueue(this) }

Slide 26

Slide 26 text

GOT INTERNET? val apiService = ApiClient.client?.create(ApiInterface::class.java) val call = apiService?.discoverMovies(API_KEY) call?.enqueue(this) } withConnection {

Slide 27

Slide 27 text

asyncExecutor( heavyFunction = { MovieApplication.movieDataBase?.movieDao()?.getAll() }, response = { response -> response?.forEach { /**/ }} ) fun asyncExecutor(heavyFunction: () -> T, response : (response : T?) -> Unit) { async(UI) { val data : Deferred = bg { heavyFunction() } response(data.await()) } } FUNCTIONS AS OBJECTS

Slide 28

Slide 28 text

VISIBILITY EXTENSIONS fun View.isVisibile(): Boolean = this.visibility == View.VISIBLE fun View.makeVisible() { this.visibility = View.VISIBLE } fun List.showViews() { this.forEach { view -> view.makeVisible() } }

Slide 29

Slide 29 text

CONTEXT EXTENSIONS fun Context.dpToPx(dp : Int): Float { val displayMetrics = this.resources.displayMetrics return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)).toFloat() } fun Context.getColorCompat(@ColorRes colorInt: Int) : Int = ContextCompat.getColor(this, colorInt)

Slide 30

Slide 30 text

GENERAL EXTENSIONS fun ByteArray.convertBytesToBitmap(): Bitmap = BitmapFactory.decodeByteArray(this, 0, size) fun Double.celsiusToFahrenheit() : Double = (this * 1.8) + 32 fun String.convertStringToDate(simpleDateFormatPattern: String): Date? { val simpleDateFormat = SimpleDateFormat(simpleDateFormatPattern, Locale.getDefault()) var value: Date? = null justTry { value = simpleDateFormat.parse(this) } return value }

Slide 31

Slide 31 text

SYNTACTIC SUGARS CAN CAUSE DIABETES ▸ Good looking code may not always be best at performance. ▸ Look for downsides before writing a snippet whose usage may get accelerated.

Slide 32

Slide 32 text

DON’T JUDGE BOOK BY IT’S COVER

Slide 33

Slide 33 text

PUTTING ON THE DETECTIVE HAT

Slide 34

Slide 34 text

BACK TO JAVA WORLD

Slide 35

Slide 35 text

GET IN-LINE Kotlin’s doc for use of Inline Functions Decompiled to Java

Slide 36

Slide 36 text

WHEN CODING

Slide 37

Slide 37 text

LOOK BEFORE CODE ▸ Analyze your code before jumping into code. ▸ Don’t over-engineer. ▸ You may not need extensions or higher order functions. ▸ Performance analyze your code. ▸ Examine before writing, the logic you just wrote may already be present in existing libraries. ▸ Single parameter functions are best candidate for conversion to extension function.

Slide 38

Slide 38 text

CONTEXT EXTENSIONS IN FRAGMENTS AND ACTIVITIES inline fun Context.withConnection(block: () -> Unit) { if (isNetworkStatusAvailable()) { block() } } inline fun Fragment.withConnection(block: () -> Unit) { this.context?.withConnection { block() } } // In Activity withConnection { } //Fragment context?.withConnection {} // In Fragment withConnection { }

Slide 39

Slide 39 text

JUST DON’T fun debugOrElse(blockIf: () -> Unit, blockElse: () -> Unit) { if (BuildConfig.DEBUG) { blockIf.invoke() } else { blockElse.invoke() } } debugOrElse({ StrictMode.enableDefaults() }, { Timber.plant(ReleaseTree())})

Slide 40

Slide 40 text

JUST DON’T fun debugOrElse(blockIf: () -> Unit, blockElse: () -> Unit) { if (BuildConfig.DEBUG) { blockIf.invoke() } else { blockElse.invoke() } } debugOrElse({ StrictMode.enableDefaults() }, { Timber.plant(ReleaseTree())})

Slide 41

Slide 41 text

JUST DON’T fun debugOrElse(blockIf: () -> Unit, blockElse: () -> Unit) { if (BuildConfig.DEBUG) { blockIf.invoke() } else { blockElse.invoke() } } debugOrElse({ StrictMode.enableDefaults() }, { Timber.plant(ReleaseTree())}) if (BuildConfig.DEBUG) { StrictMode.enableDefaults() } else { Timber.plant(ReleaseTree()) }

Slide 42

Slide 42 text

BE SMART - USE ANKO

Slide 43

Slide 43 text

THAT’S IT ▸ https://github.com/jitinsharma/Kotlin.someExtensions ▸ https://android.jlelse.eu/playing-with-kotlin-higher-order- functions-aecce3d72a12 ▸ https://twitter.com/js_2892

Slide 44

Slide 44 text

Q&A