Rebugger : A recomposition debugger
Being a "compose dev" our enemy number one is unnecessary recompositions π€. Often times we use tools like recompositionHighligher, LogComposition, and layout inspector to count the recomposition, but thereβs no direct way to understand "why" the recomposition has happened.
Rebugger is a simple compose utility function that can track the change in the given arguments. Itβll print the reason for recomposition in your Logcat window.
Kotlin Script
repositories {
...
mavenCentral()
}
dependencies {
// [latest version - i promise!]
implementation("io.github.theapache64:rebugger:1.0.1")
}Groovy
repositories {
...
mavenCentral()
}
dependencies {
// [latest version - i promise!]
implementation 'io.github.theapache64:rebugger:1.0.1'
}Call
Rebuggerwith the states or args you want to track
@Composable fun VehicleUi( car: Car, bike: Bike, ) { var human by remember { mutableStateOf(Human("John")) } // Call Rebugger and pass the states you want to track. // It could be a function arg or a state Rebugger( trackMap = mapOf( "car" to car, "bike" to bike, "human" to human ), ) //...
Search for
Rebugger
- When Rebugger hooked into your composable, itβll print something like this
- When VehicleUi recomposes due to car instance change
- When VehicleUi recomposes due to both car and bike instance change
- When VehicleUi recomposes due to human instance change (State within the composable)
You can use the RebuggerConfig.init function to override default properties of Rebugger.
class App : Application() { // ... override fun onCreate() { super.onCreate() // ... RebuggerConfig.init( tag = "MyAppRebugger", // changing default tag logger = { tag, message -> Timber.i(tag, message) } // use Timber for logging ) } }
You can use the Rebugger IntelliJ plugin to generate the Rebugger function call.
Screen.Recording.2023εΉ΄05ζ01ζ₯.at.10.42.57.PM.mov
When Rebugger is placed deep inside the composable, it may not be able to pick the correct composable name. For example, if I place the Rebugger somewhere inside the Button lambda like this
@Composable fun VehicleUi( car: Car, bike: Bike, ) { // ... Column { // ... Button( onClick = { //... } ) { // π Inside Button's content lambda Rebugger( trackMap = mapOf( "car" to car, "bike" to bike, "human" to human ), ) // ... } } }
Itβll print something like this
To fix this, you can pass composableName argument to override the automatic name picking behaviour
Rebugger( composableName = "Button's body", trackMap = mapOf( "car" to car, "bike" to bike, "human" to human ), )