android 当具有ViewModel参数时,Jetpack合成预览不显示

2izufjch  于 2022-12-02  发布在  Android
关注(0)|答案(2)|浏览(198)

我在使用Jetpack Compose时发现预览没有显示。我读过类似this的文章,但问题的根本原因似乎不同。甚至我还在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(
             ...
        )
    }
}

当我回滚一些更改时,我意识到@Preview不支持viewModels,无论它们是否注入了Hilt。
你知道怎么解决吗?

k2arahey

k2arahey1#

你有没有考虑过这样一个结构,你有一个Screen和实际的Content分开这样?

// data class
data class AccountData(val accountInfo: Any?)

// composable "Screen", where you define contexts, viewModels, hoisted states, etc
@Composable
fun AccountScreen(viewModel: AccountViewModel = hiltViewModel()) {

    val accountData = viewModel.accountDataState.collectAsState()

    AccountContent(accountData = accountData) {
        // click callback
    }
}

//your actual composable that hosts your child composable widget/components
@Composable
fun AccountContent(
    accountData: AccountData,
    clickCallback: () ->
) {
   ...
}

在那里你可以预览Content的样子

@Preview
@Composable
fun AccountContentPreview() {

    // create some mock AccountData
    val mockData = AccountData(…)
    AccountContent(accountData = mockData) {
         // I'm not expecting some actual ViewModel calls here, instead I'll just manipulate the mock data
    }
}

通过这种方式,所有不需要由实际内容可组合组件配置的组件都被分离,从而使您摆脱了配置预览的麻烦。
只是一个补充说明,可能离题了,我刚刚注意到你有一个这样的参数,

speech: SpeechHelper = SpeechHelper()

您可以考虑使用compositionLocalProvider(如果需要),它可以清理您的参数。

qhhrdooz

qhhrdooz2#

通过将ViewModels的函数 Package 到数据类中,我设法实现了屏幕预览的可视化,如下所示:

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

我没有在compose中直接传递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 = {} 
)

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

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

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

 ....
}

在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()
                )
            }
        }
    
        ...
    }

这是有点复杂,但它的工作:D.我会很高兴,如果有一些彗星的改进。

相关问题