Previews rot faster than tests, because nothing fails when they break. Here is what keeps mine useful past week two.
Take parameters, not a ViewModel
A preview that constructs a ViewModel is a preview that needs a repository, which needs a database. Split the screen in two: a stateful wrapper that talks to the ViewModel, and a stateless one that takes data.
@Composable
fun PuzzleScreen(viewModel: PuzzleViewModel) {
val state by viewModel.state.collectAsStateWithLifecycle()
PuzzleContent(state = state, onCell = viewModel::onCell)
}
@Preview
@Composable
private fun PuzzlePreview() {
PuzzleContent(state = PuzzleState.sample, onCell = {})
}
Only PuzzleContent gets previewed, and it cannot break for environmental
reasons.
Keep sample data next to the model
A sample on the companion object stays in step with the model, because it stops
compiling when the model changes. Sample data in the preview file does not.
Preview the states that are hard to reach
Loading, empty, error, and the longest string a translator might hand you. Those are the states you cannot easily produce on a device, which is exactly why the preview is worth having.