Decompose is a Kotlin Multiplatform library for breaking down your code into tree-structured lifecycle-aware business logic components (aka BLoC), with routing functionality and pluggable UI. The Decompose Detekt Rules are a set of custom detekt rules that help you avoid critical mistakes when working with Decompose.
Specify the dependency on this set of rules using detektPlugins
:
detektPlugins("io.github.ajiekcx.detekt:decompose-detekt-rules:0.2.0")
A common mistake is to create a Decompose ComponentContext
inside a Composable function scope. For example:
class MainActivity: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// DON'T DO THIS
val context = defaultComponentContext()
}
}
}
If recomposition occurs without Activity recreation, you will get the following exception:
java.lang.IllegalArgumentException: SavedStateProvider with the given key is already registered
Avoid using the defaultComponentContext
function inside Composable functions.
Decompose uses the kotlinx.serialization library to serialize component configurations. A common mistake is naming a property the same as the class discriminator (default: "type"). For example:
import kotlinx.serialization.Serializable
@Serializable
sealed class ScreenConfig {
@Serializable
data object Input : ScreenConfig()
@Serializable
data class Details(
val message: String,
val type: String // DON'T DO THIS
) : ScreenConfig()
}
If Decompose attempts to serialize this component configuration, you will encounter the following exception:
java.lang.IllegalStateException: Sealed class 'ScreenConfig.Details' cannot be serialized as base class 'ScreenConfig' because it has property name that conflicts with JSON class discriminator 'type'.
Do not name properties in polymorphic serializable classes as a class discriminator.
By default, all rules are enabled, but you can configure them in your detekt.yml
configuration file:
DecomposeRuleSet:
DecomposeComponentContextRule:
active: true
SerializableDiscriminatorRule:
active: true
classDiscriminator: 'type' # optional