D-KMP architecture - official sample
This is the official sample of the D-KMP architecture, presenting a simple master/detail app, for Android, iOS and Desktop.
(the Web version will be added at a later stage, when "Compose for Web" and "Kotlin/Wasm" become more mature)
Key features of the D-KMP architecture:
- it uses the latest declarative UI toolkits: Compose for Android and SwiftUI for iOS
- it fully shares the ViewModel (including navigation logic and data layer) via Kotlin MultiPlatform
- coroutine scopes are cancelled/reinitialized automatically, based on the current active screens and the app lifecycle (using LifecycleObserver on Android and the SwiftUI lifecycle on iOS)
- it implements the MVI pattern and the unidirectional data flow
- it implements the CQRS pattern, by providing Command functions (via Events and Navigation) and Query functions (via StateProviders)
- it uses Kotlin's StateFlow to trigger UI layer recompositions
- the navigation state is processed in the shared code, and then exposed to the UI layer:
- on SwiftUI it seamlessly integrates with the new iOS 16 navigation patterns (NavigationStack and/or NavigationSplitView)
- on Compose it's a "remembered" data class which works on any platform (unlike Jetpack Navigation, which only works on Android)
you can find more info on these articles:
- D-KMP sample now leverages iOS 16 navigation (february 2023)
- The future of apps: Declarative UIs with Kotlin MultiPlatform (D-KMP) (november 2020)
Data sources used by this sample:
- webservices (using Ktor Http Client)
- local db (using SqlDelight)
- local settings (using MultiplaformSettings)
these are other data sources, not used by this sample, for which popular KMP libraries exist:
- realtime db (using Firestore)
- graphQL (using Apollo GraphQL)
- device bluetooth (using Kable)
- etc...
Instructions to write your own D-KMP app:
If you want to create your own app using the D-KMP Architecture, here are the instructions you need:
SHARED CODE:
View Model
π οΈ in the viewmodel/screens folder: create a folder for each screen of the app, containing these 3 files (as shown in the sample app structure above):- screenEvents.kt, where the event functions for that screen are defined
- screenInit.kt, where the initialization settings for that screen are defined
- screenState.kt, where the data class of the state for that screen is defined
π οΈ in the NavigationSettings.kt file in the screens folder, you should define your level 1 navigation and other settingsπ οΈ in the ScreenEnum.kt file in the screens folder, you should define the enum with all screens in your appβ the ScreenInitSettings.kt file in the screens folder doesn't need to be modifiedβ the 6 files in the viewmodel folder (DKMPViewModel.kt, Events.kt, Navigation.kt, ScreenIdentifier.kt, StateManager.kt, StateProviders.kt) don't need to be modifiedβ also DKMPViewModelForAndroid.kt in androidMain and DKMPViewModelForIos.kt in iosMain don't need to be modified
Data Layer
π οΈ in the datalayer/functions folder: create a file for each repository function to be called by the ViewModel's StateReducersπ οΈ in the datalayer/objects folder: create a file for each data class used by the repository functionsπ οΈ in the datalayer/sources folder: create a folder for each datasource, where the datasource-specific functions (called by the repository functions) are definedβ the datalayer/Repository.kt file should be modified only in case you want to add an extra datasource
PLATFORM-SPECIFIC CODE:
Android
β the App.kt file doesn't need to be modifiedβ the MainActivity.kt file doesn't need to be modified- The composables are used by both Android and Desktop apps:
π οΈ the Level1BottomBar.kt and Level1NavigationRail.kt files in the navigation/bars folder should be modified to custom the Navigation bars itemsβ the TopBar.kt file in the navigation/bars folder doesn't need to be modifiedβ the OnePane.kt and TwoPane.kt files in the navigation/templates folder don't need to be modifiedβ the HandleBackButton.kt file in the navigation folder doesn't need to be modifiedβ the Router.kt file in the navigation folder doesn't need to be modifiedπ οΈ in the ScreenPicker.kt file in the navigation folder, you should define the screen composables in your appπ οΈ in the screens folder: create a folder for each screen of the app, containing all composables for that screenβ the MainComposable.kt file doesn't need to be modified
iOS
π οΈ the Level1BottomBar.swift and Level1NavigationRail.swift files in the composables/navigation/bars folder should be modified to custom the Navigation bars itemsβ the TopBar.swift file in the composables/navigation/bars folder doesn't need to be modifiedβ the OnePane.swift and TwoPane.swift files in the composables/navigation/templates folder don't need to be modifiedβ the Router.swift file in the composables/navigation folder doesn't need to be modifiedπ οΈ in the ScreenPicker.swift file in the views/navigation folder, you should define the screen composables in your appπ οΈ in the views/screens folder: create a folder for each screen of the app, containing all SwiftUI views for that screenβ the App.swift file doesn't need to be modifiedβ the AppObservableObject.swift file doesn't need to be modified
Desktop
β the main.kt file doesn't need to be modified- The composables are used by both Android and Desktop apps:
- look at the description on the Android section above
Web (not yet implemented)
- The best technology to implement a Web App in Kotlin will be Compose for Web backed by Kotlin/Wasm. However Kotlin/Wasm is still at a very early stage: the first version was just released in February 2023, with Kotlin 1.8.20.
- Compose For Web and Kotlin/Wasm will allow us to build Compose projects seamlessly for the Web, using the same composables we are already using for the Desktop and Android.