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

Architectures with Kotlin Multiplatform

Jitin
March 30, 2019

Architectures with Kotlin 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. Modern apps are build on top of abstractions and architectures which make sure code-bases remain mature, testable and error free. They on the other hand also introduce a lot of boilerplate code. This presents an opportunity of code reuse with help of Kotlin multiplatform. Through this talk, we’ll see how can harness power of Kotlin Multiplatform to create apps using architectures such as MVP, MVI etc and use Kotlin native to build an abstraction layer across platforms. We’ll also go through usage of various multiplatform libraries for database and network management.

Jitin

March 30, 2019
Tweet

More Decks by Jitin

Other Decks in Technology

Transcript

  1. Most popular among Android Developers Was designed with platform agnostic

    behaviour. Has a lot of features which can targeted outside JVM environment.
  2. Interop C/Objective C interop provided System frameworks are automatically imported

    in case of iOS. Types are mapped with Swift/Objective C.
  3. Multiplatform One Language to rule them all Started with Kotlin

    1.2 Still in experimental phase. Built in tooling with IntellijIDEA.
  4. common android iOS js server project - Presentation logic -

    ui-logic - Data models - Helper/utilities - Networking - Storage - Data models - Networking? - Storage?
  5. app commonMain main iosMain iosApp .kt,xml .kt .kt Imports common

    libraries Imports iOS libraries Builds Android app Builds .framework .swift, xib
  6. expect fun <T : Comparable<T>> MutableList<T>.sort(): Unit val names =

    mutableListOf("Bumblebee", "Optimus Prime", "Megatron") names.sort() public actual fun <T : Comparable<T>> MutableList<T>.sort(): Unit { if (size > 1) java.util.Collections.sort(this) } MutableCollectionsJVM.kt CollectionsH.kt Foo.kt
  7. NetworkClient.kt class NetworkClient { private val client = HttpClient() fun

    get(url: String, callback: (String) -> Unit) { GlobalScope.launch(ApplicationDispatcher) { val result: String = client.get { url(url) } callback(result) } } } internal expect val ApplicationDispatcher: CoroutineDispatcher
  8. internal expect val ApplicationDispatcher: CoroutineDispatcher import platform.darwin.dispatch_async import platform.darwin.dispatch_get_main_queue import

    platform.darwin.dispatch_queue_t internal actual val ApplicationDispatcher: CoroutineDispatcher = NsQueueDispatcher(dispatch_get_main_queue() internal class NsQueueDispatcher(private val dispatchQueue: dispatch_queue_t) : CoroutineDispatcher() { override fun dispatch(context: CoroutineContext, block: Runnable) { dispatch_async(dispatchQueue) { block.run() } } } IOSDispatcher.kt
  9. Serialization @Serializable data class AllData( val avatar_url: String?, val bio:

    String?, val blog: String, .... ) import kotlinx.serialization.*
  10. Persistence - SQLDelight CREATE TABLE Photos ( id INTEGER NOT

    NULL, title TEXT NOT NULL ); insert: INSERT INTO Photos (id, title) VALUES (?, ?); getAll: SELECT * FROM Photos;
  11. Persistence expect val db: Database db.photoQueries.getAll() -> List<Photo> //iOS actual

    val db = Database(NativeSqliteDriver(Database.Schema, "photo.db")) //Android actual val db = Database(AndroidSqliteDriver(Database.Schema, context, “photo.db"))
  12. class DataRepository { private val api = NetworkApi("https://github.com") fun getData(username:

    String, callback : (Data) -> Unit) { val data = api.getAll(username) { callback(it) } } }
  13. class MainPresenter(private val view: MainView, private val repository: DataRepository) {

    fun loadData(userName: String) { if (userName.isNullOrEmpty()) { view.showError(USER_NAME_NOT_VALID) } else { view.showLoader() repository.getData(userName) { showData() view.hideLoader() } } } }
  14. extension ViewController: MainView { func showLoader() { activityIndicator.startAnimating() } func

    hideLoader() { activityIndicator.stopAnimating() } func displayData(data: DisplayData) { .... } } ViewController.swift
  15. expect val store: Store<AppState> expect class AppState : StateType expect

    fun appReducer(action: Action, state: AppState?): AppState class LoadRecentPhotos : Action class SerializeResponse(val response: String) : Action Actions.kt Common
  16. actual val store: Store<AppState> = Store( state = AppState(), reducer

    = ::appReducer, middleware = listOf(networkMiddleWare, databaseMiddleWare) ) actual data class AppState(val photoListState: PhotoListState? = null) : StateType actual fun appReducer(action: Action, state: AppState?): AppState { return AppState(photoListState = photoListReducer(action, state?.photoListState)) } Android
  17. Performance Generated framework binaries are smaller in size. Few extra

    classes are generated for various kotlin types For Android/JVM there is not much impact.
  18. Debugging For Android/JVM projects, both common code and android code

    can be debugged right from IDE. For iOS, generated framework files can be debugged accordingly.
  19. Testing Shared code test cases can be written out of

    IntelliJ using kotlin.test Platform specific execution using platform test libraries. Existing platform libraries(espresso, xctest) can still be used.
  20. DIY Multiplatform Libraries common android iOS ./gradlew build library.jar library.framework

    Multiplatform Publishing library-common.jar library-android.jar library-ios.klib .module
  21. DIY Multiplatform Libraries common android iOS ./gradlew build library.jar library.framework

    Multiplatform Publishing library-common.jar library-android.jar library-ios.klib .module maven, pod
  22. What’s great Language - Kotlin No external dependencies as in

    custom runtime/ VM Pragmatic APIs Platform specific libs with common Kotlin code