具有 ViewModel 参数时,Jetpack Compose 预览不显示

MeL*_*ine 6 android kotlin android-jetpack-compose android-jetpack-compose-preview

我正在使用 Jetpack Compose,并注意到预览未显示。我读过这样的文章,但我的问题似乎有不同的根本原因。即使我为 compose 函数中的所有参数添加了默认值,如下所示:

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
@ExperimentalFoundationApi
@Preview
fun VolumeSettingsScreen(
    speech: SpeechHelper = SpeechHelper(), // my class that converts text to speech
    viewModel: VolumeSettingsViewModel = hiltViewModel(), // using Hilt to inject ViewModels
    navController: NavHostController = rememberNavController() // Compose Navigation component
) {
    MyAppheme {
        Box(
             ...
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

当我回滚一些更改时,我意识到无论它们是否注入了 Hilt,都不@Preview支持。viewModels

知道如何解决这个问题吗?

MeL*_*ine 4

我通过将 ViewModel 的函数包装到数据类中,成功地可视化了屏幕的预览,如下所示:

@OptIn(ExperimentalLifecycleComposeApi::class)
@Composable
@ExperimentalFoundationApi
@Preview
fun VolumeSettingsScreen(
    modifier: Modifier = Modifier,
    speechCallbacks: SpeechCallbacks = SpeechCallbacks(),
    navigationCallbacks: NavigationCallbacks = NavigationCallbacks(),
    viewModelCallbacks: VolumeSettingsScreenCallbacks = VolumeSettingsScreenCallbacks()
) {
    MyAppheme {
        Box(
             ...
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

我没有直接在组合中传递 ViewModel,而是在 Data 类中传递所需的函数,例如,如下所示:

data class VolumeSettingsScreenCallbacks(
    val uiState: Flow<BaseUiState?> = flowOf(null),
    val onValueUpSelected: () -> Boolean = { false },
    val onValueDownSelected: () -> Boolean = { false },
    val doOnBoarding: (String) -> Unit = {},
    val onScreenCloseRequest: (String) -> Unit = {} 
)
Run Code Online (Sandbox Code Playgroud)

我创建了一个在 ViewModel 中生成这些回调的方法,如下所示:

@HiltViewModel
class VolumeSettingsViewModel @Inject constructor() : BaseViewModel() {

    fun createViewModelCallbacks(): VolumeSettingsScreenCallbacks =
        VolumeSettingsScreenCallbacks(
            uiState = uiState,
            onValueUpSelected = ::onValueUpSelected,
            onValueDownSelected = ::onValueDownSelected,
            doOnBoarding = ::doOnBoarding,
            onScreenCloseRequest = ::onScreenCloseRequest
        )

 ....
}
Run Code Online (Sandbox Code Playgroud)

在 NavHost 中,我像这样提升了 ViewModel 的创建:

    @Composable
    @ExperimentalFoundationApi
    fun MyAppNavHost(
        speech: SpeechHelper,
        navController: NavHostController,
        startDestination: String = HOME.route,
    ): Unit = NavHost(
        navController = navController,
        startDestination = startDestination,
    ) {
        ...
    
        composable(route = Destination.VOLUME_SETTINGS.route) {
            hiltViewModel<VolumeSettingsViewModel>().run {
                VolumeSettingsScreen(
                    modifier = keyEventModifier,
                    speechCallbacks = speech.createCallback() // my function,
                    navigation callbacks = navController.createCallbacks(), //it is mine extension function                  
                    viewModelCallbacks = createViewModelCallbacks()
                )
            }
        }
    
        ...
    }
Run Code Online (Sandbox Code Playgroud)

虽然有点复杂,但是很有效:D。如果有一些彗星需要改进,我会很高兴。