One of the features of Android Studio is the Layout Inspector, which lets you know how many recompositions have been executed and how many recompositions have been skipped. However, it is impossible to know which fields have been changed and recomposed, and if it is a large project, the Layout Inspector may sometimes not work or there may be a delay in screen update.
I experienced the above inconveniences while using Layout Inspector, so I developed a plugin that separates the recomposition tracing feature of Layout Inspector into its own plugin.
ComposeInvestigator
The plugin I developed is open source and is called ComposeInvestigator.
https://github.com/jisungbin/ComposeInvestigator?source=post_page—–e9800db1419e——————————–
Let’s introduce it using Now In Android as an example project. It’s straightforward to use. You only need to add a single line to the Gradle plugin.
plugins {
id("land.sungbin.composeinvestigator") version "1.5.10-0.1.0"
}
Then let’s run the app to see the logcat.
When you search with ComposeInvestigator, you can see that various logs are output.
ComposeInvestigator outputs a total of four kinds of logs.
1. Recomposition request
This is when a recomposition is requested. Internally, Compose results in either “Proceed to recomposition” or “Skip recomposition” when a recomposition is requested.
ComposeInvestigator The 'ForYouRoute' composable has been invalidated.
Processed(reason=[Invalidate] An invalidation has been requested for the current composable scope. The state value in the body of that composable function has most likely changed.
2. Recomposition process
The recomposition is actually in progress. In this case, the output shows which arguments in the recomposed composable have been changed.
3. State variable value changes
To help determine the cause when recomposition is performed, it is also output when the value of the State
variable changes.
ComposeInvestigator The state of 'searchQuery' inside 'SearchRoute' composable has changed. previousValue=Hello, Worl, newValue=Hello, World
4. Skip recomposition
A recomposition was requested but skipped because no fields were changed.
In addition, you can use various runtime functions to solve more problems or register callbacks to be executed on a case-by-case basis.
For example, when you have multiple composables with the same name, it’s not always easy to recognize which composable is represented in logcat.
In this case, you can use the currentComposableInvalidationTracker.currentComposableName
API to temporarily rename the composable. These changes are only valid in ComposeInvestigator’s logs.
Also, if the same composable is used in multiple files, it’s not always easy to recognize which file’s composable is represented in the logcat. This can be solved by changing the recomposition trace logging format to add the composable call stack to the log.
ComposeInvestigatorConfig.invalidationLogger = ComposableInvalidationLogger { callstack, composable, type ->
Log.d(
"ComposeInvestigator",
"The '${composable.name}' composable has been invalidated.\n(${callstack.joinToString(separator = " -> ")})\n$type"
)
}
Job Offers
Additional runtime API usage can be found in ComposeInvestigator’s official documentation. And if you’re curious about the under-the-hood, the official documentation also explains how it works.
Working on the ComposeInvestigator project also gave me a solid understanding of Jetpack Compose’s recomposition behavior. This will be written in a separate post.
I hope you find ComposeInvestigator useful. Thank you.
https://github.com/jisungbin/ComposeInvestigator?source=post_page—–e9800db1419e——————————–
https://jisungbin.github.io/ComposeInvestigator/?source=post_page—–e9800db1419e——————————–
This article is previously published on proandroiddev.com