Jetpack Compose with more complex Previews/ Live previews and ViewModels

Sebastian Rieger
4 min readSep 4, 2021

--

My team and I are really impressed how fast we can build new frontends with Jetpack Compose. What starts as a simple library integration to our project leads to a really cool pattern to create interactive previews for which you don’t need an emulator or real device to test and try.

We designed a pattern which is fast to implement and really helpful when you want to try out something new within your layout.

The Problem

We are struggling with a problem I found a lot while learning Jetpack Compose. How can we create a Compose Preview with more complex data types?

First Solution

Our first approach was to create the Method signature with default values as you can see below.

This works well for a single element, but it leads to an extreme long list when you combine different elements in more complex layouts.

So we start to think, what can we do?

Use the ViewModel

My first idea was to give the layout an instance of the ViewModel we already have, but this causes different problems.

Our ViewModels are using Dependency Injection. For more complex things we are injection Services, wich are doing tasks like persisting data to databases or load data from our backend services. But the preview is not able to create complex things like a Room Database.

Also we have had problems with app states and so on. So we couldn't do the following.

We are getting lots of errors from Compose, because it tried to load things which are only present on an emulator or real device. I faced my Team with the problem and someone said “What about an Interface?”

What about an Interface?

“An Interface?” “How can an interface help us?” was my first reaction. But after a little time we created the following solution which I will describe to you in more detail now.

The Solution

Let’s create an Interface of the ViewModel and see what we can do with it.

So, now we have created an interface and exposed all functions and values the layout interacts with. But Jetpack Compose needs a specific instance as default value to create a preview. This looks like the code below.

We have now a static implementation of the interface with which Jetpack Compose can finally work.

Now you can link the methods and values of the ViewModel to the components of your layout. Just passing the members and lambdas of the ViewModel to your compose funktions.

We have now created a powerful approach to work with Jetpack Compose, but we did a runtime mistake! Do you have seen that we instantiate “composeViewModel” every time we create an instance of the ViewModel? We should change it to the following.

With the “by lazy” in line 11 we are only creating the composeViewModel instance when it’s needed. Because the instance isn’t needed at runtime we don’t waste resources with this approach.

And that's all! We are now passing a mocked instance of our ViewModel to Jetpack Compose as default value which is overwritten at runtime.

Advantages

There are some advantages to use an interface as we will see now.

Override things when needed

Do you need a preview with specific values? No problem, just use the “apply” function to change the default values to a specific values for only a single preview.

Live Preview

Create a clickable Compose preview without the emulator or a real device.

At first you have to enable the feature within the Android Studio preferences und “Experimental”.

Enable the interactive Live preview

Great, you have enabled the Live preview!

Now you can use the interactive mode by clicking the following symbol:

Interactive mode

But wait! Nothing will change by clicking on it till you have defined some methods within the “composeViewModel”. So, lets do this.

Great, now you have an interactive Jetpack Compose preview which can be edited very easily. It’s possible to change the behavior of the mock right in front of your client.

We are happy with this little trick and I hope you are too.

If this article was helpful for you, don’t forget to 👏

If there is something wrong or not understandable leave a comment so that I can improve this article!

--

--

Sebastian Rieger

Hi, I’m Sebastian. Check out me Website riegersan.com for more information about me or you can find me on Twitter @rieger_san