SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG - - PowerPoint PPT Presentation

shipping multiplatform on ios android ben asher alec
SMART_READER_LITE
LIVE PREVIEW

SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG - - PowerPoint PPT Presentation

SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG @benasher44 @strongolopolis Copenhagen Denmark SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG @benasher44 @strongolopolis Copenhagen Denmark Markups


slide-1
SLIDE 1

Copenhagen Denmark

SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG

@benasher44 @strongolopolis

slide-2
SLIDE 2

Copenhagen Denmark

SHIPPING MULTIPLATFORM ON IOS & ANDROID BEN ASHER ALEC STRONG

@benasher44 @strongolopolis

slide-3
SLIDE 3

Link to another sheet Markups

slide-4
SLIDE 4

History

slide-5
SLIDE 5

Live Info

slide-6
SLIDE 6

Championed on iOS ~15 across Android and iOS Construction Championed on Android ~30 across Android and iOS Financial Services

slide-7
SLIDE 7

Offline Sync System Search Business Logic

slide-8
SLIDE 8

Business Logic Models

slide-9
SLIDE 9

MPP

Business Logic Models

slide-10
SLIDE 10

MPP

Business Logic Models

slide-11
SLIDE 11

MPP

slide-12
SLIDE 12

MPP Kotlin/Native

slide-13
SLIDE 13
slide-14
SLIDE 14
slide-15
SLIDE 15
slide-16
SLIDE 16

New tools New language Uneven ecosystem

🌯🌯🌯 🌯🌯🌯

slide-17
SLIDE 17

Adopting cross-platform in your app has a cost

slide-18
SLIDE 18

What is the value that makes it worth the effort?

slide-19
SLIDE 19

Diverging Sync Systems

slide-20
SLIDE 20
slide-21
SLIDE 21
slide-22
SLIDE 22

Existing Shared Code

slide-23
SLIDE 23

What tools will your cross-platform solution need What is the common goal all stakeholders have

slide-24
SLIDE 24

What else?

No JNI

  • n Android

Obj-C
 Interop Not New For Android Community Jetbrains

slide-25
SLIDE 25

Common Questions

Kotlin/Native relies on Obj-C? What about Swift?

Obj-C header is well-annotated for Swift This is the status quo for Apple’s own frameworks

slide-26
SLIDE 26

Common Questions

What about performance?

Same performance expectations on Android Can drop into C if needed on iOS

slide-27
SLIDE 27

Common Questions

What about value types?

slide-28
SLIDE 28

Common Questions

There’s a garbage collector? But there’s no JVM, right? Bacon’s Algorithm for GC

slide-29
SLIDE 29

Common Questions

What libraries can we use for mpp?

JVM Distributions are incomplete Special multiplatform distributions K/N ABI instability (klib)

slide-30
SLIDE 30

Common Questions

What is “common” code?

slide-31
SLIDE 31

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets

slide-32
SLIDE 32

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets Code expect class Lock actual class Lock actual class Lock

slide-33
SLIDE 33
slide-34
SLIDE 34
slide-35
SLIDE 35

expect class Lock actual class Lock actual class Lock

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets

slide-36
SLIDE 36

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets

slide-37
SLIDE 37

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets

slide-38
SLIDE 38

commonMain iosMain androidMain iOS - .framework Android - .aar

Library Outputs Library Source Sets

windowsMain Windows - .dll

slide-39
SLIDE 39

Is it platform agnostic? commonMain

Yes No

Will other common code use it?

Yes No

Platform

slide-40
SLIDE 40

Is it platform agnostic? commonMain

Yes No

Will other common code use it?

Yes No

Platform

slide-41
SLIDE 41
slide-42
SLIDE 42

Is it platform agnostic?

No

Will other common code use it? commonMain

Yes

slide-43
SLIDE 43

expect class DatabaseFactory { internal fun createSqliteDriver(): SqlDriver }

slide-44
SLIDE 44

Is it platform agnostic?

No

Will other common code use it?

No

Platform

slide-45
SLIDE 45

sourceSets {A commonMain {B}C androidLibMain {D}E iosLibMain {F}G }H

slide-46
SLIDE 46

sourceSets {A commonMain {B}C androidLibMain {D dependencies {I api project(‘:protos') }J }E iosLibMain {F}G }H

slide-47
SLIDE 47

fun SearchQueries.insert(entity: SyncEntity) entity: SyncEntity

slide-48
SLIDE 48

sourceSets {A commonMain {B}C androidLibMain {D}E iosLibMain {F}G }H

slide-49
SLIDE 49

sourceSets {A commonMain {B}C androidLibMain {D}E }H

slide-50
SLIDE 50

Is it platform agnostic? commonMain

Yes

slide-51
SLIDE 51

fun search(terms: String): List<Search>?

slide-52
SLIDE 52

commonMain iosMain androidMain

Library Source Sets

Host
 Application

slide-53
SLIDE 53

Host
 Application

Talks to backend API Talks to existing application state

slide-54
SLIDE 54

Host
 Application commonMain

Library Initialization

Library defines interface App provides implementation

slide-55
SLIDE 55
slide-56
SLIDE 56

Highly platform-specific Backend API Hosts Current user’s credential

Case Study: Networking

slide-57
SLIDE 57

Make an API request Receive an async response Interface can be re-implemented later

MPP Life Hack: Interface Network

slide-58
SLIDE 58

interface Network { /** * Makes an API request */ fun makeRequest( host: APIHost, request: Request, completion: (Request.Response) -> Unit ): NetworkDisposable }

slide-59
SLIDE 59

interface Network { /** * Makes an API request */ fun makeRequest( host: APIHost, request: Request, completion: (Request.Response) -> Unit ): NetworkDisposable } host: APIHost Plain enum of names of the hosts– no URL handling required

slide-60
SLIDE 60

interface Network { /** * Makes an API request */ fun makeRequest( host: APIHost, request: Request, completion: (Request.Response) -> Unit ): NetworkDisposable } request: Request data class:

  • String path and body,
  • query params dict
  • enum method (GET, POST, etc.)
slide-61
SLIDE 61

interface Network { /** * Makes an API request */ fun makeRequest( host: APIHost, request: Request, completion: (Request.Response) -> Unit ): NetworkDisposable } completion: (Request.Response) -> Unit sealed class w/ different response types:

slide-62
SLIDE 62

interface Network { /** * Makes an API request */ fun makeRequest( host: APIHost, request: Request, completion: (Request.Response) -> Unit ): NetworkDisposable } NetworkDisposable Interface with a cancel() method

slide-63
SLIDE 63

suspend fun Network.makeRequest( host: APIHost, request: Request ): Request.Response

slide-64
SLIDE 64

Concurrency in commonMain

commonMain iosMain androidMain

expect fun <T> T.freeze(): T actual fun <T> T.freeze(): T = this actual fun <T> T.freeze(): T = freeze()

slide-65
SLIDE 65
slide-66
SLIDE 66
slide-67
SLIDE 67

Shipping Internally

commonMain iosMain androidMain Host
 Application

slide-68
SLIDE 68

commonMain iosMain androidMain Host
 Application Host
 Application

slide-69
SLIDE 69

commonMain iosMain androidMain Host
 Application Host
 Application

slide-70
SLIDE 70

Pros Cons

Minimal change for android Seamless local development Single source of truth Host dependencies Two build environments for iOS CI Nightmare

slide-71
SLIDE 71

commonMain iosMain androidMain Host
 Application Host
 Application

slide-72
SLIDE 72

commonMain iosMain androidMain Host
 Application Host
 Application

slide-73
SLIDE 73

commonMain commonMain iosMain androidMain Host
 Application Host
 Application

slide-74
SLIDE 74

commonMain iosMain androidMain Host
 Application Host
 Application commonMain

slide-75
SLIDE 75

Pros Cons

Minimal change for android Seamless local development Host dependencies Two build environments for iOS CI Nightmare for iOS Out of sync code

slide-76
SLIDE 76
slide-77
SLIDE 77
slide-78
SLIDE 78

commonMain iosMain androidMain Host
 Application Host
 Application

slide-79
SLIDE 79

commonMain iosMain androidMain Host
 Application Host
 Application

slide-80
SLIDE 80

Pros Cons

CI is fast Encourages unit test coverage Single source of truth Breaking changes are painful Need good CD setup Debugging decoupled repos

slide-81
SLIDE 81

commonMain iosMain androidMain Host
 Application Host
 Application

slide-82
SLIDE 82

commonMain iosMain Host
 Application Host
 Application androidMain

slide-83
SLIDE 83

commonMain androidMain Host
 Application Host
 Application

slide-84
SLIDE 84

Shipping Externally Test Crashing!

slide-85
SLIDE 85

Shipping Externally

fun crash() { (null as String?)!! }

slide-86
SLIDE 86

Shipping Externally

setUnhandledExceptionHook()

slide-87
SLIDE 87

Shipping Externally What happens if a Worker crashes?

slide-88
SLIDE 88
slide-89
SLIDE 89
slide-90
SLIDE 90
slide-91
SLIDE 91
slide-92
SLIDE 92
slide-93
SLIDE 93

Define your project’s goals Be thoughtful growing your codebase Avoid solving general muliplatform problems Get your CI and dev setup working early Join us in Kotlin slack

Review

slide-94
SLIDE 94

#KotlinConf

THANK YOU AND REMEMBER TO VOTE

Ben Asher @benasher44 Alec Strong @Strongolopolis