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

A tale of Multiplatform

Ce1ca64f3265f01a8718a622427f0a1d?s=47 Jitin
August 04, 2019

A tale of Multiplatform

In the current wave of cross-platform solutions, Kotlin’s multiplatform is shaping up to be a unique proponent of code reuse. Unlike write once run everywhere, Multiplatform offers a unique space of reusability and formalization of code across platforms and also removes dependency on custom VMs or runtime. Through this talk, we'll go through building an app for Android and iOS and use Kotlin multiplatform for code sharing and building an abstraction layer across platforms.

Ce1ca64f3265f01a8718a622427f0a1d?s=128

Jitin

August 04, 2019
Tweet

More Decks by Jitin

Other Decks in Technology

Transcript

  1. None
  2. Hello!!

  3. BYJU’S The Learning app @iamBedant

  4. Gojek The Super app @_jitinsharma

  5. Multiplatform A tale of @iamBedant | @_jitinsharma HISTORY KOTLIN MP

    KOTLIN ANDROID & IOS SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  6. History of Platforms

  7. A Long time ago…

  8. System A we have

  9. O 1 System A

  10. 0 1 1 0 0 0 O 1 1 1

    0 0 1 0 1 1 0 1 1 0 0 0 O 1 0 0 1 0 1 0 O 1
  11. START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 INT

    21H MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H MOV AH,1
  12. START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 INT

    21H MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H MOV AH,1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  13. 0 1 0 1 0 0 1 0 1 1

    1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  14. 0 1 0 1 0 0 1 0 1 1

    1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  15. 0 1 0 1 0 0 1 0 1 1

    1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  16. START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 INT

    21H MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H MOV AH,1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0 Code 1
  17. START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 INT

    21H MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H MOV AH,1 START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H LEA DX,MSG3 Code 1 Code 2
  18. START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 INT

    21H MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H MOV AH,1 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0 START: MOV AX,DATA MOV DS,AX LEA DX,MSG1 MOV AH,9 MOV AH,1 INT 21H SUB AL,30H MOV NUM1,AL LEA DX,MSG2 MOV AH,9 INT 21H LEA DX,MSG3 Code 1 Code 2
  19. 0 1 0 1 0 0 1 0 1 1

    1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  20. C / C++

  21. #include <stdio.h> int main() { !" printf() displays the string

    inside quotation printf("Hello, World!"); return 0; } C / C++
  22. #include <stdio.h> int main() { !" printf() displays the string

    inside quotation printf("Hello, World!"); return 0; } 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  23. #include <stdio.h> int main() { !" printf() displays the string

    inside quotation printf("Hello, World!"); return 0; } 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  24. J V M HISTORY KOTLIN MP KOTLIN ANDROID & IOS

    SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  25. class HelloWorld { public static void main(String args[]) { System.out.println("Hello,

    World"); } }
  26. class HelloWorld { public static void main(String args[]) { System.out.println("Hello,

    World"); } } HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  27. JVM JVM HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE

    APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  28. JVM JVM HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE

    APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  29. JVM JVM HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE

    APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  30. W E B

  31. <!DOCTYPE HTML> <html> <body> <p>Before the script...</p> <script> alert( 'Hello,

    world!' ); </script> <p>...After the script.</p> </body> </html>
  32. <!DOCTYPE HTML> <html> <body> <p>Before the script...</p> <script> alert( 'Hello,

    world!' ); </script> <p>...After the script.</p> </body> </html> 0 1 0 1 0 0 1 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 1 1 0
  33. Multiplatform HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP

    VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  34. None
  35. Byte Code JavaScript Native Binary objective c

  36. Byte Code JavaScript Native Binary objective c kotlinc kotlinc-js LLVM

  37. LLVM

  38. IR LLVM

  39. IR LLVM

  40. IR LLVM

  41. IR LLVM

  42. LLVM

  43. LLVM

  44. LLVM Konan

  45. Byte Code JavaScript Native Binary .framework kotlinc kotlinc-js LLVM

  46. None
  47. None
  48. .jar

  49. .jar .js

  50. .jar .js .framework

  51. None
  52. HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE

    PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  53. ▸ Create UI. ▸ Create Models. ▸ Call Api. ▸

    Parse Response. ▸ Add Business Logic. ▸ Store in DB Task
  54. Task ▸ Create UI. ▸ Create Models. ▸ Call Api.

    ▸ Parse Response. ▸ Add Business Logic. ▸ Store in DB
  55. Task ▸ Create UI. ▸ Create Models. ▸ Call Api.

    ▸ Parse Response. ▸ Add Business Logic. ▸ Store in DB
  56. Task ▸ Create UI. ▸ Create Models. ▸ Call Api.

    ▸ Parse Response. ▸ Add Business Logic. ▸ Store in DB
  57. None
  58. Task ▸ Create UI. ▸ Create Models. ▸ Call Api.

    ▸ Parse Response. ▸ Add Business Logic. ▸ Store in DB
  59. Task ▸ Create UI. ▸ Create Models. ▸ Call Api.

    ▸ Parse Response. ▸ Add Business Logic. ▸ Store in DB
  60. ▸ Create Models. ▸ Parse Response. ▸ Add Business Logic.

    ▸ Call Api. ▸ Store in DB ▸ Create UI.
  61. Network Call

  62. HTTP - GET - POST - PUT - host -

    contentType - headers - Serialize - Threading
  63. ktor

  64. private val httpClient = HttpClient { install(JsonFeature){ serializer = KotlinxSerializer().apply

    { setMapper(AllData#$class, AllData.serializer()) } } install(ExpectSuccess) } Ktor
  65. private val httpClient = HttpClient { install(JsonFeature){ serializer = KotlinxSerializer().apply

    { setMapper(AllData#$class, AllData.serializer()) } } install(ExpectSuccess) } Ktor
  66. Ktor fun getAll(userId: String, callback: (String) %& Unit) { GlobalScope.launch(NetworkDispatcher)

    { val result: String = client.get { protocol = URLProtocol.HTTPS host = "api.github.com" encodedPath = "users/$userId" } callback(result) } }
  67. Ktor fun getAll(callback: (String) %& Unit) { GlobalScope.launch(NetworkDispatcher) { val

    result: String = client.get { protocol = URLProtocol.HTTPS host = "newsapi.org/v2" encodedPath = "top-headlines?country=us" } callback(result) } }
  68. Ktor fun getAll(callback: (String) %& Unit) { GlobalScope.launch(NetworkDispatcher) { val

    result: String = client.get { protocol = URLProtocol.HTTPS host = "newsapi.org/v2" encodedPath = "top-headlines?country=us" } callback(result) } }
  69. Ktor internal expect val NetworkDispatcher: CoroutineDispatcher

  70. Ktor internal expect val NetworkDispatcher: CoroutineDispatcher internal actual val NetworkDispatcher

    = Dispatchers.Default Android
  71. import platform.darwin.dispatch_async import platform.darwin.dispatch_get_main_queue import platform.darwin.dispatch_queue_t internal class NsQueueDispatcher(private val

    dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() { override fun dispatch(context: CoroutineContext, block: Runnable) { dispatch_async(dispatchQueue) { block.run() } } }
  72. import platform.darwin.dispatch_async import platform.darwin.dispatch_get_main_queue import platform.darwin.dispatch_queue_t internal class NsQueueDispatcher(private val

    dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() { override fun dispatch(context: CoroutineContext, block: Runnable) { dispatch_async(dispatchQueue) { block.run() } } }
  73. import platform.darwin.dispatch_async import platform.darwin.dispatch_get_main_queue import platform.darwin.dispatch_queue_t internal class NsQueueDispatcher(private val

    dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() { override fun dispatch(context: CoroutineContext, block: Runnable) { dispatch_async(dispatchQueue) { block.run() } } }
  74. Ktor internal expect val NetworkDispatcher: CoroutineDispatcher iOS internal actual val

    NetworkDispatcher = NsQueueDispatcher(dispatch_get_main_queue())
  75. Storage

  76. Sqlite

  77. Sqlite - Queries - Transactions - host - contentType -

    headers - Serialize - Threading
  78. sqldelight

  79. CREATE TABLE BookmarkedArticle ( author TEXT NOT NULL, content TEXT

    NOT NULL, ); insert: INSERT INTO BookmarkedArticle (author, content) VALUES (?,?); getAll: SELECT * FROM BookmarkedArticle; BookmarkedArticle.sq
  80. CREATE TABLE BookmarkedArticle ( author TEXT NOT NULL, content TEXT

    NOT NULL, ); insert: INSERT INTO BookmarkedArticle (author, content) VALUES (?,?); getAll: SELECT * FROM BookmarkedArticle; BookmarkedArticle.sq
  81. CREATE TABLE BookmarkedArticle ( author TEXT NOT NULL, content TEXT

    NOT NULL, ); insert: INSERT INTO BookmarkedArticle (author, content) VALUES (?,?); getAll: SELECT * FROM BookmarkedArticle; BookmarkedArticle.sq
  82. SqlDelight var newsDatabase = Database(driver)

  83. AndroidSqliteDriver(Database.Schema, context, “article.db") NativeSqliteDriver(Database.Schema, "article.db") var newsDatabase = Database(driver) iOS

    Android SqlDelight
  84. newsDatabase.bookmarkedArticleQueries.insert(...) newsDatabase.bookmarkedArticleQueries.getAll().executeAsList()

  85. newsDatabase.bookmarkedArticleQueries.insert(...) newsDatabase.bookmarkedArticleQueries.getAll().executeAsList() insert: INSERT INTO BookmarkedArticle (author, content) VALUES (?,?);

    getAll: SELECT * FROM BookmarkedArticle;
  86. Architecture

  87. - Repository - Presenter - Storage/Network - Activity - ViewController

  88. None
  89. None
  90. None
  91. None
  92. None
  93. None
  94. None
  95. None
  96. None
  97. None
  98. None
  99. class MainPresenter(private val view: MainView, private val dataRepository: DataRepository) {

    fun loadData() { view.showLoader() dataRepository.getTopHeadLines { view.displayHeadLines(it.mapToNewsArticleList()) view.hideLoader() } } fun storeArticle(newsArticle: NewsArticle) { dataRepository.saveArticle(newsArticle) } }
  100. class MainPresenter(private val view: MainView, private val dataRepository: DataRepository) {

    fun loadData() { view.showLoader() dataRepository.getTopHeadLines { view.displayHeadLines(it.mapToNewsArticleList()) view.hideLoader() } } fun storeArticle(newsArticle: NewsArticle) { dataRepository.saveArticle(newsArticle) } }
  101. class MainPresenter(private val view: MainView, private val dataRepository: DataRepository) {

    fun loadData() { view.showLoader() dataRepository.getTopHeadLines { view.displayHeadLines(it.mapToNewsArticleList()) view.hideLoader() } } fun storeArticle(newsArticle: NewsArticle) { dataRepository.saveArticle(newsArticle) } }
  102. interface MainView : BaseView { fun showLoader() fun hideLoader() fun

    displayHeadLines(headlines: List<NewsArticle>) fun displayBookmarkedHeadLines(headlines: List<NewsArticle>) }
  103. class MainActivity : AppCompatActivity(), MainView { override fun displayHeadLines(headlines: List<NewsArticle>)

    {...} override fun showLoader() {...} override fun hideLoader() {...} override fun showError(error: String) {...} private val mainPresenter by lazy { inject<MainPresenter>() } override fun onCreate(savedInstanceState: Bundle?) { mainPresenter.loadData() } }
  104. class MainActivity : AppCompatActivity(), MainView { override fun displayHeadLines(headlines: List<NewsArticle>)

    {...} override fun showLoader() {...} override fun hideLoader() {...} override fun showError(error: String) {...} private val mainPresenter by lazy { inject<MainPresenter>() } override fun onCreate(savedInstanceState: Bundle?) { mainPresenter.loadData() } }
  105. class MainActivity : AppCompatActivity(), MainView { override fun displayHeadLines(headlines: List<NewsArticle>)

    {...} override fun showLoader() {...} override fun hideLoader() {...} override fun showError(error: String) {...} private val mainPresenter by lazy { inject<MainPresenter>() } override fun onCreate(savedInstanceState: Bundle?) { mainPresenter.loadData() } }
  106. class ViewController: UIViewController , MainView { func displayHeadLines(headlines: [NewsArticle]) {...}

    func showError(error: String) {...} func showLoader() {...} func hideLoader() {...} lazy var presenter : MainPresenter = { IOSInjectorKt.injectMainPresenter() }() override func viewDidLoad() { super.viewDidLoad() presenter.loadData() } }
  107. class ViewController: UIViewController , MainView { func displayHeadLines(headlines: [NewsArticle]) {...}

    func showError(error: String) {...} func showLoader() {...} func hideLoader() {...} lazy var presenter : MainPresenter = { IOSInjectorKt.injectMainPresenter() }() override func viewDidLoad() { super.viewDidLoad() presenter.loadData() } }
  108. class ViewController: UIViewController , MainView { func displayHeadLines(headlines: [NewsArticle]) {...}

    func showError(error: String) {...} func showLoader() {...} func hideLoader() {...} lazy var presenter : MainPresenter = { IOSInjectorKt.injectMainPresenter() }() override func viewDidLoad() { super.viewDidLoad() presenter.loadData() } }
  109. HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE

    PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES ios Android web WhatÊs great
  110. - Kotlin language - No custom runtime - Platform specific

    libraries with common kotlin code HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES WhatÊs great
  111. WhatÊs not great - Dependency on multiplatform libs for better

    code sharing - Still experimental HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES RESOURCES
  112. Resources - https://kotlinlang.org/docs/reference/multiplatform.html - https://github.com/Kotlin/kotlinx.coroutines - https://github.com/square/sqldelight - https://github.com/Kotlin/kotlinx.serialization -

    https://ktor.io/clients/http-client/multiplatform.html - https://github.com/iamBedant/Multiplatform-Sample HISTORY KOTLIN MP KOTLIN ANDROID & IOS SAMPLE APP VALUE PROPOSITION ADVANTAGES DISADVANTAGES RESOURCES
  113. Thank you!! @iamBedant @_jitinsharma