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

Kotlin Extensions and Higher Order Functions (B...

Jitin
February 10, 2018

Kotlin Extensions and Higher Order Functions (BlrKotlin Meetup, Feb 2018)

Kotlin's modern features has made it a go-to language for Android Developers. This talk will be focussed on how extension functions and higher order functions can help developers write more declarative code, avoid pitfalls and in the end make their application more reliable. We will also discuss caveats related to these features and how to overcome them to avoid any performance issues.

Jitin

February 10, 2018
Tweet

More Decks by Jitin

Other Decks in Programming

Transcript

  1. 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.
  2. fun Double.toFahrenheit() : Double = (this * 1.8) + 32

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

    val f = 34.toFahrenheit() //call like this fun Boolean.toString() : String = "abc" true.toString() //"true"
  4. 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
  5. KOTLIN 101 - REMOVE THEM NULL CHECKS ▸ if (someObject

    != null) { } ▸ someObject?.let { it-> }
  6. 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
  7. 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 } } }
  8. 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.
  9. DIY

  10. DO IT YOURSELF // interface for item click // initialize

    interface // setting interface method on click // getting on click in main class JAVA WAY
  11. 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
  12. inline fun <T> justTry(block: () -> T) = try {

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

    block() } catch (_: Throwable) { // log here } GENERAL FUNCTIONALITIES fun String.toIntOrZero() : Int { var value = 0 justTry { value = this.toInt() } return value }
  14. asyncExecutor( heavyFunction = { MovieApplication.movieDataBase?.movieDao()?.getAll() }, response = { response

    -> response?.forEach { /**/ }} ) fun <T> asyncExecutor(heavyFunction: () -> T, response : (response : T?) -> Unit) { async(UI) { val data : Deferred<T> = bg { heavyFunction() } response(data.await()) } } FUNCTIONS AS OBJECTS
  15. VISIBILITY EXTENSIONS fun View.isVisibile(): Boolean = this.visibility == View.VISIBLE fun

    View.makeVisible() { this.visibility = View.VISIBLE } fun List<View>.showViews() { this.forEach { view -> view.makeVisible() } }
  16. 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)
  17. 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 }
  18. 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.
  19. 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.
  20. 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 { }
  21. JUST DON’T fun debugOrElse(blockIf: () -> Unit, blockElse: () ->

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

    Unit) { if (BuildConfig.DEBUG) { blockIf.invoke() } else { blockElse.invoke() } } debugOrElse({ StrictMode.enableDefaults() }, { Timber.plant(ReleaseTree())})
  23. 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()) }
  24. Q&A