Reputation: 5233
I have such an implementation:
...
@Composable
private fun PhoneVerificationCodeScreen(vm: MyViewModel) {
Column(...) {
...
OTPBlock(numberOfCells = NUMBER_OF_OTP_CELLS, isVerifyBtnEnabledState = vm.isVerifyBtnEnabledState)
...
}
}
...
There is my preview function:
class MyViewModelProvider : PreviewParameterProvider<MyViewModel> {
override val values: Sequence<MyViewModel> = sequenceOf(MyViewModel(
SavedStateHandle()
))
}
@Preview(
name = "Phone-portrait",
device = Devices.PHONE,
showBackground = true,
backgroundColor = 0x111,
showSystemUi = true
)
@Composable
private fun PhonePreviewVerificationCodeScreen(
@PreviewParameter(MyViewModelProvider::class) vm: MyViewModel
) = PhoneVerificationCodeScreen(vm = vm)
SPOILER: before I included ViewModel as a param it worked as expected.
I went through a few solutions in the google and the last one I tried was by using PreviewParameterProvider
, however, it doesn't work as well.
So, the question is - how to "preview" the compose function that takes a param?
ERROR is:
java.lang.ClassNotFoundException: my_package.VerificationCodeViewModelProvider at java.lang.ClassLoader.loadClass at java.lang.ClassLoader.loadClass at java.lang.Class.forName0 at java.lang.Class.forName at androidx.compose.ui.tooling.ComposableInvoker.invokeComposable
Upvotes: 0
Views: 1970
Reputation: 648
Probably not the answer you are looking for but I'd extract the viewmodel from the composables, so instead of this:
@Composable
MyComposable(viewModel: MyViewModel) {
Button(onClick = {
viewModel.buttonClicked()
}) {
Text(text = viewModel.state.myText)
}
}
It'd be something like this
val viewModel: YourViewModel = viewModel()
val state: MyState = viewModel.state
@Composable
MyComposable(
state: MyState,
onViewEvent: (MyViewEvents) -> Unit,
) {
Button(onClick = {
onViewEvent(MyViewEvents.buttonClicked)
}) {
Text(text = state.myText)
}
}
This also allows you to make any number of previews with different states.
Upvotes: 2
Reputation: 4185
The method recommended on the Android developers site for creating previews of composables with ViewModels is to create an inner composable that accepts the ViewModel parameters as arguments:
@Composable
fun MyComposable(viewModel: MyViewModel) {
val state by viewModel.state.collectAsStateWithLifecycle()
MyComposable(
state = state
)
}
@Composable
fun MyComposable(state: MyState) {
...
}
Then create a preview for the inner composable:
@Preview
@Composable
fun MyComposablePreview(state: MyState = MyState()) {
MyComposable(state = state)
}
See: https://developer.android.com/jetpack/compose/tooling/previews#preview-viewmodel
There are various other methods as well, such as using an interface and creating a preview instance of the interface.
Upvotes: 1