Jetpack Compose π: Run Preview with Hilt
How to run preview compassable with hiltViewModel()
dependency injection in emulator.
One of the awesome features Jetpack Compose provide is to run any piece of Composable independently speeding up build time, testing Composable in isolation, and developing behavior faster with the use of Preview
annotation.
Whenever you slap @Preview
annotation over a composable it gives a small icon as in the image below :

Once you click on it and select Run
it will run code scoped to this composable in the emulator.
What Magic is does under the hood βοΈ
If you investigate other options, you can see there is modify run configuration

which gives you hint that it has something to do run configuration
, can you guess where same option appears in IDE? Hint π

If you click on Modify Run Configuration
from Preview Action, window to modify run configuration for the composable open.

Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donationπ°
Similarly, exact same window is opened when you open option Edit configuration
and select Compose Preview
.

making it clear that whenever you add @Preview
annotation to a composable and run it, IDE
recognise it as a new Run Configuration
entry.
What Run Configuration Does π΅π»ββοΈ
For Compose Preview
behind the scenes it launches an Activity called PreviewActivity
from the compose-ui tooling package

Which extends ComponentActivity
thus having the functionality to call setContent

which runs the target composable using reflection api :

So basically with some ui-tooling library and IDE magic IDE has given you a shortcut of quick run option.
Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donationπ°
Issue with Hilt Dependency Injection π
Dependency Injection plays a major role in software applications in abstracting all the ceremonies related to the creation of dependencies, and Android's ViewModel has been infamous for the complexities involved with its creation.
To ease the pain Google has recommended Hilt
as a DI solution than Dagger, abstracting all the boilerplate code behind annotations, which works absolute wonders for our codebase, is not so friendly is UI tooling of Compose, especially with the Preview functionality.
Here is the link for Jetpack Compose hilt Integration in case you want to go-through the API
If you need explanation and advance examples related to Hilt which is not mentioned in guide do drop a post request in form at end of article.
TLDR π
You use hiltViewModel()
function to inject Android ViewModels into your composable
Example of Constructing and Injecting ViewModel Looks like :

Clear and Simple right!, but now if you try to run
the Preview Composable :
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)Β
Caused by: java.lang.ClassNotFoundException: Composable Method 'com.proptiger.ui.components.buttons.SampleKt.ButtonPreview' not found
at androidx.compose.ui.tooling.CommonPreviewUtils.invokeComposableViaReflection$ui_tooling_release(CommonPreviewUtils.kt:196)
at androidx.compose.ui.tooling.PreviewActivity$setComposableContent$2.invoke(PreviewActivity.kt:72)
at androidx.compose.ui.tooling.PreviewActivity$setComposableContent$2.invoke(PreviewActivity.kt:71)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.ui.platform.ComposeView.Content(ComposeView.android.kt:384)
.... and 1000 more lines of bla bla ....
If you analyse the logs it will say ClassNotFoundException
, at ui_tooling_release
ClassNotFoundException: Composable Method 'io.github.ch8n.compose97.ui.components.buttons.SampleKt.ButtonPreview' not found at androidx.compose.ui.tooling.CommonPreviewUtils.invokeComposableViaReflection$ui_tooling_release(
Which sounds like UI Tooling Related issue, which might be the case, but this crash doesn't happen if :

If you remove the dependency in the parameter. I didnβt dig more deep into it, but from an overview It appears the source of Β could be Hilt
to inject dependency. For Hilt to work Correctly the Parent Activity needs to be marked with @AndroidEntryPoint
annotation.
Thus with MainActivity which we have marked @AndroidEntryPoint
this code works flawlessly for running into emulator.

But in case of our PreviewActivity
which is provided by Compose UI Tooling, this annotation is not provided.
So Actually there is no way right now to make @Preview
annotation functional with Hilt
unless some compatibility is provided by the Android tooling team.
Are we done? π΅βπ« no solution?

We can't actually do anything about PreviewActivity
, but we can make our own run configuration
which could run our own PreviewActivity with @AndroidEntryPoint
annotation
Setting up Custom Run Configuration π
Step 1 : Create an Empty Activity, I call it HiltPreviewActivity
, not need to Create Layout for it.

Step 2 : Copy-Paste Following Code
@AndroidEntryPoint
class HiltPreviewActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
}
}
}
Note : Don't blindly copy-paste, check the name of your Activity, yours might be different.
Step 3 : Go back to Edit Configurations...

Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donationπ°
Step 4 : Select +
option to add New Configuration.

Step 5 : Select Android App
Configuration Option

Step 6 : Β Enter Name
, I choose HiltPreview. then Select App
Module of your project.

Step 7 : Select Specific Activity
from Launch Option Section

Step 8 : Select HiltPreviewActivity
, and finally complete with Apply
, then ok
.

New Option of HiltPreview would be visible in your run configuration .

Do we create our own @Preview Composable? π€
Well NO!, the slapping @Preview
and getting launch icon short cut is IDE
magic, we can't really do that, and this is the limitation of this method.
To run your Preview Composable, you need to manually paste them inside of setContent{..}
of our created Activity.

Which isn't such a downside if you look at it.
Anyways if anyone has a way to automate this. Do reach me out, but again don't spend that much effort its an overkill.
Note : Don't Forget to Wrap our Composable into MaterialTheme{..}
composable else you will miss out fonts and styles.
Conclusion ππ»ββοΈ
Above method let you add custom run configuration that run Activity with Hilt dependency applied to you don't get the crash. Down side is you need to manually paste preview composable into its set content. Hope it helps and speeds up you android development builds!
Until Next Time ! Happy Hacking π¨π»βπ»
Enjoy the article?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
Reach me out :

Enjoying the Post?
a clap is much appreciated if you enjoyed. No sign up or cost associated :)
If you want to support my content do consider dropping a tip/coffee/donationπ°