我有以下代码.理想情况下,我将使用onPreferenceChange: (Preferences.Key) -> Unit来调用viewModel函数,该函数将假定泛型类型为Pferencs.Key,类型为值.但是,这会产生以下错误:One type argument expected for class Key<T>

简单的方法可能是将viewModel作为ScreenBody的参数传递,但指导方针似乎不建议这样做(子级应将事件传递给父级(S)),并 destruct Composable预览

编辑:首选项的类型.键可以是字符串、布尔值、整数、双精度、集

我怎么能在这里继续呢?

@Composable
fun SettingsScreen(
    modifier: Modifier = Modifier,
    viewModel: SettingsScreenViewModel = viewModel(factory = ViewModelProvider.Factory),
) {
    Scaffold {
        SettingsScreenBody(
            onPreferenceChange = viewModel::setPreferenceValue,
            modifier = Modifier.padding(innerPadding),
        )
    }
}

@Composable
private fun SettingsScreenBody(
    onPreferenceChange: (key: Preferences.Key, value: Any) -> Unit,
    modifier: Modifier = Modifier,
) {
        // App Theme
        ListPreference(
            title = R.string.pref_title_app_theme,
        ) { newValue ->
            onPreferenceChange(PreferenceRepository.Keys.NIGHT_MODE, newValue)
        }
}

class SettingsScreenViewModel(
    private val preferenceRepository: PreferenceRepository,
): ViewModel() {

    val preferences = preferenceRepository.preferences

    fun <T> setPreferenceValue(key: Preferences.Key<T>, value: T) {
        viewModelScope.launch { preferenceRepository.set(key, value) }
    }

}

object Keys {
    val NIGHT_MODE: Preferences.Key<String> = stringPreferencesKey("night_mode")
    val METRIC_UNITS: Preferences.Key<Boolean> = booleanPreferencesKey("metric_units")
    // other keys of Int and Double types
}

enter image description here

推荐答案

在修改了代码as suggested by CommonsWare之后,我找到了一种可以接受的解决方法.似乎解决方案是使用函数体而不是传递函数引用,这样代码就会产生以下结果(只发布受更改影响的代码,其余代码保持不变):

@Composable
fun SettingsScreen(
    modifier: Modifier = Modifier,
    viewModel: SettingsScreenViewModel = viewModel(factory = ViewModelProvider.Factory),
) {
    Scaffold {
        SettingsScreenBody(
            onPreferenceChange = { key, value ->                           //
                viewModel.setPreferenceValue(key, value)                   // CHANGE 1
            },                                                             //
            modifier = Modifier.padding(innerPadding),
        )
    }
}


@Composable
private fun SettingsScreenBody(
    onPreferenceChange: (key: Preferences.Key<*>, value: Any) -> Unit,     // CHANGE 2
    modifier: Modifier = Modifier,
) {
    // App Theme
    ListPreference(
        title = R.string.pref_title_app_theme,
    ) { newValue ->
        onPreferenceChange(PreferenceRepository.Keys.NIGHT_MODE, newValue)
    }
}

Android相关问答推荐

如何自定义所选的NavigationBar项目?

listOf(listOf(字符串))在lazyArchitect(lazyStream)中合成

写入排除例外以进行依赖性判断

如何允许我的应用程序在Android 10上运行,同时目标是API 33

Android可组合继承?

无法从API访问项目详细信息

Android在NavHost中的LazyColumn中编写约束布局:error - replace()在未放置的项目上调用

如何在初始合成期间在可组合函数中调用/获取远程API中的数据[防止无限重组]

没有打开历史记录的活动意向 Select 器完成调用活动

在Jetpack Compose中,我可以配置动画以恒定的速度而不是恒定的时间运行吗?

如何将 Room Persistence 依赖项正确添加到我的 Jetack Compose Android 应用程序

Android 应用程序从 Android Studio 安装,但不是作为 .apk 在外部安装.抛出java.lang.UnsatisfiedLinkError

Jetpack Compose - 在屏幕外偏移绘制形状并使用非常大的尺寸

在 AGP 8.0 中构建失败,无法应用插件realm-android. APIandroid.registerTransform已删除

为卡片的上半部分添加一个边框,用圆角半径组合

PullRefreshIndicator 与 ScrollableTabRow 重叠

Composable 不会在单击按钮时重新组合

JCenter 是否永久关闭(10 月 31 日)?

如何为具有不同屏幕尺寸但相同密度的手机创建响应式布局?

IconButton 中可绘制的图标是黑色的,尽管它是白色的