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

Creating Great APIs With Kotlin

Creating Great APIs With Kotlin

Slides from my talk at Kotlin/Everywhere Floripa:

https://www.meetup.com/GDGFloripa/events/262037183/

David Tiago Conceição

July 13, 2019
Tweet

More Decks by David Tiago Conceição

Other Decks in Programming

Transcript

  1. Android Development if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return context.getResources() .getColor(colorId,

    context.getTheme()); } else { return context.getResources() .getColor(colorId); }
  2. Android Development public final class ColorUtils { @ColorInt public static

    int getColor( Context context, @ColorRes int colorId) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return context.getResources() .getColor(colorId, context.getTheme()); } else { return context.getResources() .getColor(colorId); } } }
  3. Extension Functions @ColorInt fun Context.getThemedColor(@ColorRes colorId: Int) = if (Build.VERSION.SDK_INT

    >= Build.VERSION_CODES.M) { this.resources.getColor(colorId, this.theme) } else { this.resources.getColor(colorId) }
  4. Extension Functions @ColorInt fun Context.getThemedColor(@ColorRes colorId: Int) = if (Build.VERSION.SDK_INT

    >= Build.VERSION_CODES.M) { this.resources.getColor(colorId, this.theme) } else { this.resources.getColor(colorId) }
  5. Extension Functions public final class ContextExtensionsKt { @ColorInt public static

    final int getThemedColor(@NotNull Context $this$getThemedColor, @ColorRes int colorId) { return Build.VERSION.SDK_INT >= 23 ? $this$getThemedColor.getResources().getColor(colorId, $this$getThemedColor.getTheme()) : $this$getThemedColor.getResources().getColor(colorId); } }
  6. Extension Functions public final class ContextExtensionsKt { @ColorInt public static

    final int getThemedColor(@NotNull Context $this$getThemedColor, @ColorRes int colorId) { return Build.VERSION.SDK_INT >= 23 ? $this$getThemedColor.getResources().getColor(colorId, $this$getThemedColor.getTheme()) : $this$getThemedColor.getResources().getColor(colorId); } }
  7. Extension Functions @ColorInt inline fun Context.getThemedColor(@ColorRes colorId: Int) = if

    (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { this.resources.getColor(colorId, this.theme) } else { this.resources.getColor(colorId) }
  8. Extension Functions useCase.execute(id, date) .lastElement() .test() .assertDefaultData(pointOfSaleNameFromItinerary) .assertExpectedState(state) private fun

    TestObserver<State>.assertExpectedState( expectedState: SomeInternalState): TestObserver<State> { assertValue { it.someInternalState == expectedState } return this }
  9. animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { onViewShowed();

    } @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} }); Arguments
  10. animation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationEnd(Animation animation) { onViewShowed();

    } @Override public void onAnimationStart(Animation animation) {} @Override public void onAnimationRepeat(Animation animation) {} }); Arguments
  11. fun Animation.listener( onAnimationStart: ((Animation) -> Unit)? = null, onAnimationEnd: ((Animation)

    -> Unit)? = null, onAnimationRepeat: ((Animation) -> Unit)? = null) { ... Default Arguments
  12. fun Animation.listener( onAnimationStart: ((Animation) -> Unit)? = null, onAnimationEnd: ((Animation)

    -> Unit)? = null, onAnimationRepeat: ((Animation) -> Unit)? = null) { this.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationRepeat(animation: Animation?) { onAnimationStart?.invoke(animation!!) ... Default Arguments
  13. data class ClassWithManyIntegers( val integerProperty: Int = 0, val anotherIntegerProperty:

    Int = 0, val someExtraIntegerProperty: Int = 0) val complexInstance = ClassWithManyIntegers() Builders
  14. data class ClassWithManyIntegers( val integerProperty: Int = 0, val anotherIntegerProperty:

    Int = 0, val someExtraIntegerProperty: Int = 0) val complexInstance = ClassWithManyIntegers( someExtraIntegerProperty = 10) Builders
  15. val firstPoint = Point(10, 10) val secondPoint = Point(20, 20)

    val firstX = firstPoint.x val firstY = firstPoint.y val secondX = secondPoint.x val secondY = secondPoint.y val plusPoint = Point(firstX + secondX, secondY + secondY) Operations
  16. val firstPoint = Point(10, 10) val secondPoint = Point(20, 20)

    val plusPoint = firstPoint + secondPoint Operations
  17. val firstPoint = Point(10, 10) val secondPoint = Point(20, 20)

    val plusPoint = firstPoint + secondPoint operator fun Point.plus(another: Point) = Point(x + another.x, y + another.y) Operators
  18. val viewGroup: ViewGroup = getViewGroup() viewGroup += view operator fun

    ViewGroup.plusAssign(view: View) = addView(view) Operators
  19. viewGroup.forEach { view -> doSomething(view) } fun ViewGroup.forEach(onEach: (View) ->

    Unit) { for (index in 0 until childCount) { onEach(getChildAt(index)) } } Functions
  20. viewGroup.forEach { view -> doSomething(view) } fun ViewGroup.forEach(onEach: (View) ->

    Unit) { for (index in 0 until childCount) { onEach(getChildAt(index)) } } Functions
  21. fun runInDatabaseTransaction(databaseFunction: (SQLiteDatabase) -> Unit) { val dataBase = getDatabase()

    try { dataBase.beginTransaction() databaseFunction(dataBase) dataBase.setTransactionSuccessful() } finally { dataBase.endTransaction() } Functions
  22. /** Returns a range from this value up to but

    excluding the specified [to] value. * If the [to] value is less than or equal to `this` value, then the returned range is empty.*/ public infix fun Int.until(to: Int): IntRange { if (to <= Int.MIN_VALUE) return IntRange.EMPTY return this .. (to - 1).toInt() } Functions
  23. val untilRange = 0 until 10 val untilCharRange = 'a'

    until 'z' val downProgression = 10 downTo 0 Functions
  24. //Mockk every { saveEvent(any(), any()) } returns Unit every {

    mock invoke "openDoor" withArguments listOf("left", "rear") } returns "OK" verify { sendMessageHandler wasNot Called } DSLs
  25. open class PossibleState class Loading : PossibleState() class Error :

    PossibleState() class Success : PossibleState() class ViewModel { var currentState: PossibleState = Loading() } State
  26. sealed class PossibleState { object Loading : PossibleState() object Error

    : PossibleState() object Success : PossibleState()} class ViewModel { var currentState: PossibleState = PossibleState.Loading } Sealed Classes
  27. class Minutes(val value: Long) class Scheduler { fun schedule( delay:

    Minutes, action: () -> Unit) { //... } } Argument Types
  28. inline class Minutes(val value: Long) class Scheduler { fun schedule(

    delay: Minutes, action: () -> Unit) { //... } } Inline classes
  29. How to know more? • Extensions: kotlinlang.org/docs/reference/extensions.html • Kotlin Android

    Extensions: kotlinlang.org/docs/tutorials/android-plugin.html • Android KTX: developer.android.com/kotlin/ktx • Keywords and Operators: kotlinlang.org/docs/reference/keyword-reference.html • Functions: kotlinlang.org/docs/reference/functions.html • MockK: mockk.io • Sealed Classes: kotlinlang.org/docs/reference/sealed-classes.html • KotlinConf 2018 - Representing State: the Kotlin Edition by Christina Lee: www.youtube.com/watch?v=-lVVfxsRjcY • Inline classes: kotlinlang.org/docs/reference/inline-classes.html
  30. Thank you! David Tiago Conceição [email protected] Android Dev BR @davidtiagoconceicao

    twitter.com/@davidtiagocon speakerdeck.com/davidtcdeveloper