Using LocalInspectionMode to hide code from your Jetpack Compose Previews

Iceberg image from Shtumf on goodfon.com

Jetpack Compose Preview are great, I’ve blogged about them before and also delivered talks on the subject. But sometimes you can’t, or don’t want to, use them for specific UI components. That does not mean you have to miss out on the usefulness of Previews!

One of the reasons why you might not be able to create a Preview for a composable is when you have an image that is downloaded from the internet. If you haven’t set up your image error handling correctly you’ll just see a blank space (or perhaps even a missing space) when your Preview renders.

Another occasion might be when you are including an API that requires initialisation somewhere in the rest of the app (which doesn’t happen when Previews are rendered). One of the times I have experienced this is when my Composable includes Firebase.analytics.logEvent and you will get a Render problem when displaying your Preview:

If you check what the problem is, you may see something like:

Failed to instantiate a Composition Local

This preview was unable to find a CompositionLocal. You might need to define it so it can render correctly.

Failed to instantiate a Composition Local
This preview was unable to find a CompositionLocal.
You might need to define it so it can render correctly.

If you check the exception you will see:

java.lang.IllegalStateException: Default FirebaseApp is not initialized 
in this process null. Make sure to call FirebaseApp.initializeApp(Context)
first.
at com.google.firebase.FirebaseApp.getInstance(FirebaseApp.java:179)

Removing the Firebase call will fix the issue and the Preview will display.

Ideally, our Composables should be stateless and have all the information passed into them so Previews will not require internet or API access but often, this is just not practical especially if you want to initiate analytics calls.

And sometimes, you just want to show something different in your Preview than what you want to show in the live version because it makes more sense (although, this shouldn’t take the place of using well-crafted PreviewParameters and may cause bloat in your composables — so only use it when you have a good reason).

Enter LocalInspectionMode.

LocalInspectionMode provides a CompositionLocal (part of the data that is passed into the composable) which you can query to determine if this composable instance is locally inspectable — which is true if this composable is in a Preview.

Then, to check if your composable is in a preview you can use:

LocalInspectionMode.current

You can then use this to exclude code from being run if the composable is being run inside a Preview or add extra code if needed.

A simple example of conditionally including some text:

When we look at the Preview versus the emulator:

Preview on the left, emulator on the right.

We can see that text is different based on where it is displayed.

Some other examples:

As we can see, the previews are showing the alternate content:

Pretty easy!

Source link