我有以下处理数据存储首选项的代码,我想知道如何使用View Models实现它,然后访问可组合视图中的数据.此外,我还想知道如何在视图模型中处理改进后的HTTP请求,因为据我所知,最佳实践是将数据Mutations 和数据处理放在UI组件之外.我假设我需要两个数据模型,一个用于首选项,另一个用于HTTP请求数据.任何帮助都将不胜感激.谢谢.

val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

val ACCOUNT_TYPE = stringPreferencesKey("account_type")
        val accountTypeFlow: Flow<String> = applicationContext.dataStore.data
            .map { preferences ->
                preferences[ACCOUNT_TYPE] ?: ""
            }

编辑:更清楚地说,我有代码来设置和获取数据存储首选项数据,但我不知道如何在View Model中实现它,以及如何在可组合的视图中访问View Model中的数据.我还想为从Retrofit HTTP请求接收的数据创建一个View Model,但我也不确定如何做到这一点.

编辑2:我可以就Retrofit提出一个单独的问题,但我可以将第一个问题缩小到以下范围:如何在视图模型中实现数据存储变量的Get和Set功能?

推荐答案

要在ViewModel中使用DataStore个首选项,您需要创建一个ViewModel来获取和更新首选项,有点像Ethan Denvir中的"Android Compose DataStore Tutorial ".

class PreferencesViewModel(application: Application) : AndroidViewModel(application) {
    private val dataStore: DataStore<Preferences> = application.dataStore

    // LiveData to expose the account type from DataStore
    private val _accountType = MutableLiveData<String>()
    val accountType: LiveData<String> = _accountType

    init {
        viewModelScope.launch {
            fetchAccountType()
        }
    }

    private suspend fun fetchAccountType() {
        dataStore.data.map { preferences ->
            preferences[ACCOUNT_TYPE] ?: ""
        }.collect { accountTypeValue ->
            _accountType.postValue(accountTypeValue)
        }
    }

    // Function to update account type in DataStore
    fun updateAccountType(newAccountType: String) {
        viewModelScope.launch {
            dataStore.edit { preferences ->
                preferences[ACCOUNT_TYPE] = newAccountType
            }
        }
    }
}

要访问composable function中的PreferencesViewModel,可以使用viewModel() Composable(与this example中的一样)来获取ViewModelobserveAsState()的实例,以观察Composable中的LiveData As状态.

@Composable
fun PreferencesScreen(preferencesViewModel: PreferencesViewModel = viewModel()) {
    val accountType by preferencesViewModel.accountType.observeAsState("")

    Column {
        Text(text = "Account Type: $accountType")
        Button(onClick = {
            preferencesViewModel.updateAccountType("NewAccountType")
        }) {
            Text("Update Account Type")
        }
    }
}

对于处理Retrofit HTTP请求,可以使用类似的ViewModel方法,其中ViewModel将处理作出网络请求并相应地更新UI状态.


我在该代码中有一个错误:我在Composable函数中得到一个未解决的引用错误observeAsState,但我不确定原因.任何进一步的指导都将不胜感激.

首先,确保将Jetpack Compose LiveData integration library添加到模块的build.gradle文件中.如果缺少它,则需要添加它.:

dependencies {
    implementation "androidx.compose.runtime:runtime-livedata:<compose_version>"
}

<compose_version>替换为您正在使用的Compose版本.确保所有与编写相关的依赖项使用相同的版本,以避免兼容性问题.

在使用observeAsState的Kotlin文件中,确保具有以下IMPORT语句:

import androidx.compose.runtime.livedata.observeAsState

Kotlin相关问答推荐

如果一项工作失败,请继续在Kotlin 等待其他工作/子元素完成

如何使用 Kotlin Maven 更改 Minecraft 插件中的 Shulker GUI 标题

Kotlin 复制列表中的项目以创建具有相同数据的不同对象的新列表

为什么 Kotlin 在将协变类型参数转换为不变类型参数时会产生 Unchecked Cast 警告?

使用事务时未调用 Kafka ConsumerInterceptor onCommit

JavaFX - 你如何在 Kotlin 中使用 MapValueFactory?

为空数组添加值

类型不匹配:Required: Context, Found: Intent

Kotlin 方法重载

为什么我在使用 Jetpack Compose clickable-Modifier 时收到后端内部错误:Exception during IR lowering error?

Kotlin 顶级函数与对象函数

在 Kotlin 中取最后 n 个元素

Android Studio 和 Kotlin:Unresolved reference: also

如何将map函数应用于Kotlin中的数组并更改其值?

Kotlin:如何从另一个类访问字段?

如何使用mockk库模拟android上下文

Kotlin替换字符串中的多个单词

Kotlin中的函数接口

Kotlin 是否支持部分应用程序?

如何在 Kotlin 中将串联转换为模板