Code Generation
Update Generator
A common pain point with Mobius.kt is wrapping Event types to their state change functions.
In Mobius.kt this code is implemented in your Update
function, taking an event and returning a Next
instance.
Using KSP, mobiuskt-codegen
provides code generation to reduce manual boilerplate when writing complex Update
functions.
Given a sealed class Event
declaration, an interface is generated defining update methods for each Event
subclass and the exhaustive when
block in the update
method.
Example
To apply code generation, add the @GenerateUpdate
annotation to your Update function class definition:
@GenerateUpdate
class TestUpdate : Update<TestModel, TestEvent, TestEffect>, TestGeneratedUpdate {
// ...
}
Loop components (Click to expand)
Generated output
interface TestGeneratedUpdate : Update<TestModel, TestEvent, TestEffect> {
override fun update(model: TestModel, event: TestEvent): Next<TestModel, TestEffect> {
return when (event) {
TestEvent.Increment -> increment(model)
TestEvent.Decrement -> decrement(model)
is TestEvent.SetValue -> setValue(model, event)
}
}
fun increment(model: TestModel): Next<TestModel, TestEffect>
fun decrement(model: TestModel): Next<TestModel, TestEffect>
fun setValue(model: TestModel, event: TestEvent.SetValue): Next<TestModel, TestEffect>
}
Nested sealed classes
By default, nested sealed Events will produce a function for each subtype.
Child Sealed Class Default Behavior
This behavior can be changed with @DisableSubtypeSpec
, causing the sealed class to be handled by one function.
Child Sealed Class Default Behavior
Gradle Configuration
Use the following kts gradle configuration to apply the Update generator in your project:
Kotlin Gradle Script - JVM/Android (Click to expand)
plugins {
kotlin("jvm") // or kotlin("android")
id("com.google.devtools.ksp") version "<KSP-Version>"
}
kotlin {
sourceSets.main {
kotlin.srcDir("build/generated/ksp/$name/kotlin")
}
}
dependencies {
implementation("org.drewcarlson:mobiuskt-codegen-api:$mobiuskt_version")
ksp("org.drewcarlson:mobiuskt-codegen:$mobiuskt_version")
}
Kotlin Gradle Script - Multiplatform
plugins {
kotlin("multiplatform")
id("com.google.devtools.ksp") version "<KSP-Version>"
}
kotlin {
sourceSets {
val commonMain by getting {
kotlin.srcDir("build/generated/ksp/$name/kotlin")
dependencies {
implementation("org.drewcarlson:mobiuskt-codegen-api:$mobiuskt_version")
}
}
}
}
// Note this must be in a top-level `dependencies` block, not `kotlin { sourceSets { .. } }`
dependencies {
add("kspCommonMainMetadata", "org.drewcarlson:mobiuskt-codegen:$mobiuskt_version")
}
// This ensures that when compiling for any target, your `commonMain` sources are
// scanned and code is generated to `build/generated/ksp/commonMain` instead of a
// directory for the specific target. See https://github.com/google/ksp/issues/567
if (tasks.any { it.name == "kspCommonMainKotlinMetadata" }) {
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>>().all {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
}
For more details see the official KSP documentation.