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

I Walk The Line - What Should Be Kotlin/Native And What (Maybe) Shouldn't - KotlinConf, Copenhagen, Denmark, December 2019

I Walk The Line - What Should Be Kotlin/Native And What (Maybe) Shouldn't - KotlinConf, Copenhagen, Denmark, December 2019

Code:
https://github.com/bakkenbaeck/PorchPirateProtector

Abstract:
Kotlin/Native is an incredibly powerful toolset for creating cross-platform code, particularly for mobile apps. But iOS and Android both have their...quirks, particularly around handling Application, View Controller, and Fragment/Activity lifecycle. The line between getting things done more efficiently and getting sucked into a whirlpool of memory leaks can seem mighty thin, but it can be walked. In this talk, Ellen will discuss how she's walked it, what's worked -- and what definitely has not.

Ellen Shapiro

December 06, 2019
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. I WALK THE LINE WHAT SHOULD BE KOTLIN/NATIVE, AND WHAT

    (MAYBE) SHOULDN'T KOTLINCONF | COPENHAGEN, DENMARK | DECEMBER 2019 ELLEN SHAPIRO | @DESIGNATEDNERD | APOLLOGRAPHQL.COM
  2. !

  3. !

  4. Works With Kotlin? iOS app ✅ Android app ✅ Server

    ✅ Raspberry pi* ✅ * - soon, I hope
  5. MVP

  6. commonMain PRESENTER class DeviceDetailPresenter( val view: DeviceDetailView, val device: PairedDevice,

    storage: SecureStorage ): BaseCoroutinePresenter(secureStorage = storage) { // ... }
  7. commonMain VIEW interface DeviceDetailView: IndefiniteLoadingIndicating { fun setTitle(toString: String) fun

    setLockButtonEnabled(enabled: Boolean) fun setUnlockButtonEnabled(enabled: Boolean) fun setApiError(toString: String?) }
  8. ANDROID APP FRAGMENT class DeviceDetailFragment: Fragment(), DeviceDetailView { private val

    presenter by lazy { DeviceDetailPresenter( this, currentDevice, KeyStoreManager(this.context!!) ) } //... }
  9. WHAT HAVE I DONE WRONG HERE? class DeviceDetailFragment: Fragment(), DeviceDetailView

    { private val presenter by lazy { DeviceDetailPresenter( this, currentDevice, KeyStoreManager(this.context!!) ) } //... }
  10. WHAT HAVE I DONE WRONG HERE? class DeviceDetailFragment: Fragment(), DeviceDetailView

    { private val presenter by lazy { DeviceDetailPresenter( this, currentDevice, KeyStoreManager(this.context!!) ) } //... }
  11. PRESENTER class DeviceDetailPresenter( val view: DeviceDetailView, val device: PairedDevice, storage:

    SecureStorage ): BaseCoroutinePresenter(secureStorage = storage) { // ... }
  12. MVP

  13. class DeviceDetailPresenter( val device: PairedDevice ): BaseCoroutinePresenter() { data class

    DeviceDetailViewState( val lockButtonEnabled: Boolean, val unlockButtonEnabled: Boolean, val errorMessage: String? = null, val indicatorAnimating: Boolean = false ) // ... }
  14. suspend fun getStatusAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ):

    DeviceDetailViewState { // ... } suspend fun lockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //... } suspend fun unlockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //.. }
  15. suspend fun getStatusAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ):

    DeviceDetailViewState { // ... } suspend fun lockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //... } suspend fun unlockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //.. }
  16. suspend fun getStatusAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ):

    DeviceDetailViewState { // ... } suspend fun lockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //... } suspend fun unlockAsync( initialViewStateHandler: (DeviceDetailViewState) -> Unit, secureStorage: SecureStorage ): DeviceDetailViewState { //.. }
  17. import SwiftUI struct ValueView: View { var value: Double =

    0 var body: some View { return Text("\(value)") } }
  18. import SwiftUI struct ValueView: View { var value: Double =

    0 var body: some View { return Text("\(value)") } }
  19. import SwiftUI struct ValueView: View { var value: Double =

    0 var body: some View { return Text("\(value)") } }
  20. val colorPrimary = "#05C1FD" val colorPrimaryDark = "#5848F4" val colorAccent

    = "#fb5502" val colorAccentSelected = "#c94402" val textLight = "#ffffff" val textMiddle = "#777777" val textDark = "#000000" val errorRed = "#cc0000" val success = "#0d9b2a"
  21. enum class PPPColor(val hexColor: String) { ColorPrimary("#05C1FD"), ColorPrimaryDark("#5848F4"), ColorAccent("#fb5502"), ColorAccentSelected("#c94402"),

    TextLight("#ffffff"), TextMiddle("#777777"), TextDark("#000000"), ErrorRed("#cc0000"), Success("#0d9b2a"); val red: Long get() = hexColor.substring(1, 3).toLong(16) val green: Long get() = hexColor.substring(3, 5).toLong(16) val blue: Long get() = hexColor.substring(5, 7).toLong(16) }
  22. enum class PPPColor(val hexColor: String) { ColorPrimary("#05C1FD"), ColorPrimaryDark("#5848F4"), ColorAccent("#fb5502"), ColorAccentSelected("#c94402"),

    TextLight("#ffffff"), TextMiddle("#777777"), TextDark("#000000"), ErrorRed("#cc0000"), Success("#0d9b2a"); val red: Long get() = hexColor.substring(1, 3).toLong(16) val green: Long get() = hexColor.substring(3, 5).toLong(16) val blue: Long get() = hexColor.substring(5, 7).toLong(16) }
  23. import platform.UIKit.UIColor fun PPPColor.toUIColor(): UIColor { return UIColor( red =

    this.red.toDouble() / 255.0f, green = this.green.toDouble() / 255.0f, blue = this.blue.toDouble() / 255.0f, alpha = 1.0 ) }
  24. OBLIGATORY SUMMARY SLIDE > Kotlin/Native can be a double-edged sword

    > You can move way faster on some things > Be mindful of the trade-offs you're making
  25. OBLIGATORY SUMMARY SLIDE > Kotlin/Native can be a double-edged sword

    > You can move way faster on some things > Be mindful of the trade-offs you're making > Prioritize developer experience to drive adoption
  26. OBLIGATORY SUMMARY SLIDE > Kotlin/Native can be a double-edged sword

    > You can move way faster on some things > Be mindful of the trade-offs you're making > Prioritize developer experience to drive adoption > Remember why you're using K/N in the first place
  27. LINKS! > The (not so) hidden cost of sharing code

    between iOS and Android https://blogs.dropbox.com/tech/2019/08/ the-not-so-hidden-cost-of-sharing-code- between-ios-and-android/ > React Native at AirBnB https://medium.com/airbnb-engineering/ react-native-at-airbnb-f95aa460be1c