If you have any tips/tricks/ideas you think are worth including please raise new issue
- buildSrc
- Sapling
- Kotlin New Memory Model
- CFlow.kt
- KHandler.kt
- Koin.kt
- RxExtensions.kt
- KState.kt
- KController.kt
- Kotlin Multiplatform Plugin
- Xcode Kotlin
- moko-KSwift - autogenerate
Enum
forsealed class
-
Folder structure for adding dependencies to Kotlin project via class
Dependencies.kt
object Dependencies { val your_dependencies_group = mapOf( "<your_dependency_id>" to "<dependency(ex. owner:package:version)>" ) }
In your
<module>/build.gradle.kts
dependencies { Dependencies.your_dependencies_group.forEach{ implementation(it.value) } }
or
dependencies { implementation(Dependencies.your_dependencies_group["<your_dependency_id>"]) }
-
Simple KMP logging library idea-based on Timber
- Copy-paste
Sap.kt
into your project - [Optionally] Change package name
- Copy-paste
-
- add to
gradle.properties
# enable new MemModel - no object lock for thread kotlin.native.binary.memoryModel=experimental kotlin.native.binary.freezing=disabled
- add to Kotlin multiplatform module
build.gradle.kts
kotlin.targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget::class.java) { binaries.all { binaryOptions["memoryModel"] = "experimental" binaryOptions["freezing"] = "disabled" } }
- add to
-
Contains
CFlow<T>
- wrapper forkotlinx.coroutines.Flow
for mapping complex generic<T>
in iOS code- Android can use
Flow
directly - iOS can use
Flow
via.wrap().watch { /* callback */ }
// <coroutines_version = 1.6.2> org.jetbrains.kotlinx:kotlinx-coroutines-core:<coroutines_version>
// core/src/commonMain/kotlin/dev/luteoos/<ExampleKotlinController> class ExampleKotlinController<T>{ val exampleFlow = MutableStateFlow<T> // or any other Flow() fun updateExampleFlow(value: T){ CoroutineScope(Dispatchers.Main).apply { launch { exampleFlow.emit(value) } } } }
// core/src/<commonMain or iosMain>/kotlin/dev/luteoos/core class CFlow<T: any>{ ... }
// core/src/iosMain/kotlin/dev/luteoos/utils/<iosRedux> fun ExampleKotlinController.watchExampleFlow() = this.exampleFlow.wrap()
// iosApp/<ExampleIosClass> class ExampleIosClass : ObservableObject { @Published public var example: T? // ? for nullable let controller: ExampleKotlinController var exampleWatcher: Closeable? // can be made into bulk closing init(controller: ExampleKotlinController){ self.controller = controller exampleWatcher = self.controller.watchExampleFlow().watch { [weak self] example in self?.example = example } } deinit { exampleWatcher?.close } }
- Android can use
-
Kotlin Native implementation of
Handler
known from JVM for easy logic delay// <coroutines_version = 1.6.2> org.jetbrains.kotlinx:kotlinx-coroutines-core:<coroutines_version>
KHandler().postDelayed({ // your logic }, /*time in milis*/) // optionally .getJob() // returns currently running Job or null .setDispatcher(Dispatcher) // call before postDelayed to change execution Dispatcher
-
Koin.kt
- file with twofun initKoin()
- Android use
initKoin { /*<your koin modules/context here>*/ }
to initializeKoin
- iOS use
KoinKt.initKoin()
to initializeKoin
for KMM module - add your core modules inside
fun initKoin(appDeclaration: KoinAppDeclaration = {})
// <koin_core_version = 3.2.0> api("io.insert-koin:koin-core:<koin_core_version>")
import core @main struct iOSApp: App{ init(){ KoinKt.doInitKoin() } //... }
class MainApplication : Application() { override fun onCreate() { super.onCreate() initKoin{ androidContext(this@MainApplication) modules(/*your_modules*/) } } }
- Android use
-
Extension methods for easier subscription to reaktive streams such as
Observable
,Single
,Completable
// <badoo_reaktive_version = 3.2.0> implementation("com.badoo.reaktive:reaktive:<badoo_reaktive_version>")
SomeObservable<T>().resolve( onNext = { }, onError = { }, onComplete = { } ) //or SomeObservable<T>().resolve{ //it... }
-
- best use with moko-kswift gradle plugin or copy
KStateSwift.swift
to ios project
Warning when usingKStateSwift
It might generate fatal error when changed and not updated manually sealed interface
for simple state management built inKController.kt
- takes parameters
T
for data type andE
for error type - iOS usage simplified thanks for
fun
insideKState.kt
- Android usage as normal
sealed class
- States:
Success(data: T)
Error(error: E)
Loading
Empty
- best use with moko-kswift gradle plugin or copy
-
in-progress ViewController/ViewModel base
class
protected
does not exist inSwift
// <koin_core_version = 3.2.0> api("io.insert-koin:koin-core:<koin_core_version>") // <badoo_reaktive_version = 3.2.0> implementation("com.badoo.reaktive:reaktive:<badoo_reaktive_version>") implementation("com.badoo.reaktive:coroutines-interop:<badoo_reaktive_version>") // <coroutines_version = 1.6.2> implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:<coroutines_version>")
-
interface MyContorllerInterface: KControllerInterface<Data, Data>{ //... }
Mocking in swift
class MockController : KControllerInterface { func onDeInit() { print("deinit") } func onStart() { print("start") } func onStop() { print("stop") } func watchState() -> CFlow<KState> { let mockValue = /* MockState */ return CFlowCompanion().getMock(mockValue: mockValue as KState) as! CFlow<KState> }
} ```