Skip to content

Repository files navigation

🐞 Rebugger

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.

⌨️ Demo

Usage

1. Add dependencies

latestVersion

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'
}

2. Add Rebugger call

Call Rebugger with the states or args you want to track

@Composable
funVehicleUi(
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 stateRebugger(
trackMap =mapOf(
"car" to car,
"bike" to bike,
"human" to human
),
)
//...

3. See LogCat

Search for Rebugger

🖥 Sample Outputs

  • When Rebugger hooked into your composable, it’ll print something like this

image

  • When VehicleUi recomposes due to car instance change

image

  • When VehicleUi recomposes due to both car and bike instance change

image

  • When VehicleUi recomposes due to human instance change (State within the composable)

image

🎨 Customization

You can use the RebuggerConfig.init function to override default properties of Rebugger.

classApp : Application() {
// ...overridefunonCreate() {
super.onCreate()
// ...RebuggerConfig.init(
tag ="MyAppRebugger", // changing default tag
logger = { tag, message ->Timber.i(tag, message) } // use Timber for logging
)
}
}

🔌 Plugin

You can use the Rebugger IntelliJ plugin to generate the Rebugger function call.

Screen.Recording.2023-05-01.at.10.42.57.PM.mov

🟠 Limitation

Auto Name Picking

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
funVehicleUi(
car:Car,
bike:Bike,
) {
// ...Column {
// ...Button(
onClick = {
//...
}
) {
// 🟠 Inside Button's content lambdaRebugger(
trackMap =mapOf(
"car" to car,
"bike" to bike,
"human" to human
),
)
// ...
}
}
}

It’ll print something like this

image

The Fix

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
),
)

About

A simple Compose Multiplatform library designed to print the reason for recomposition in your console/Logcat window."

Topics

Resources

Stars

1.0k stars

Watchers

7 watching

Forks

Releases

Used by

Contributors

Languages