如何在视图模型中从 DataStore 首选项(如 Flow)获取值

Nic*_*400 9 android kotlin android-jetpack-datastore

我遇到了一个情况,我可以通过 SharedPreferences 解决。但现在我正在迁移到 kotlin 和 DataStore。

我遇到了这个问题。

我有一个字符串值存储在共享首选项以及其他键值对中。此字符串是一个 URL,用于 Retrofit 调用的 baseUrl 参数中。

我的问题是,当我在 ViewModel 中运行时,检索 Fragment 值的正确方法是什么。

这是我的代码的一部分:

@Singleton
class PreferencesManager @Inject constructor(
    @ApplicationContext context: Context,
    anioDao: AnioDao
) {

   val baseUrlFlow = dataStore.data
        .catch { exception ->
            if (exception is IOException) {
                Log.e(TAG, "Error reading preferences: ", exception)
                emit(emptyPreferences())
            } else {
                throw exception
            }
        }
        .map {
            it[PreferencesKeys.BASER_URL] ?: "http://192.168.2.109:1337"
        }

}
Run Code Online (Sandbox Code Playgroud)

然后在 ViewModel 类中

class EnsayosViewModel @ViewModelInject constructor(
    private val ensayoRepository: EnsayoRepository,
    private val anioRepository: AnioRepository,
    private val localidadRepository: LocalidadRepository,
    private val epocaRepository: EpocaRepository,
    private val preferencesManager: PreferencesManager,
    private val agrotrackerApi: AgrotrackerApi,
    @Assisted private val state: SavedStateHandle

) :
    ViewModel() {

...

//Base Url
val baseUrlFlow = preferencesManager.baseUrlFlow
private val _baseUrl = MutableLiveData<String>()
private fun getBaseUrl() {

    viewModelScope.launch {
        baseUrlFlow.flowOn(Dispatchers.IO).collect{
            _baseUrl.value = it
        }
    }
}

  ...

fun fetchEsayosFromAT() {

 //This is where I want to get value of the base_url key.

}
Run Code Online (Sandbox Code Playgroud)

但对于一个简单的任务来说,这似乎非常复杂......

我缺少什么?我真的迷路了。

此致

Pit*_*tos 4

获取共享偏好数据的一种方法是将 Flow 转换为 LiveData。它工作得很好,但它很可能会被 StateFlow/SharedFlow 取代作为首选方法。

  1. 在 Preference 存储库中创建一个返回 Flow 的方法

    override fun getBaseUrlPreferencesFlow(): Flow<String> = context.dataStore.data
    .catch { exception ->
        if (exception is IOException) {
            Log.e(TAG, "Error reading preferences: ", exception)
            emit(emptyPreferences())
        } else {
            throw exception
        }
    }
    .map { pref ->
       it[PreferencesKeys.BASER_URL] ?: "http://192.168.2.109:1337"
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在您的 ViewModel 中初始化 LiveData,如下所示(您可以从 ViewModel 或 Fragment 访问它)

    val baseUrlLiveData: LiveData<String> = 
    yourInjectedRepository.getBaseUrlPreferencesFlow().asLiveData()
    
    Run Code Online (Sandbox Code Playgroud)
  3. (可选)在 ViewModel 中 - 添加辅助方法来处理基本 url

    private fun processUrl(): String {
      viewModelScope.launch {
           // base url http://192.168.2.109:1337
           val url = baseUrlLiveData.value 
        }         
    }
    
    Run Code Online (Sandbox Code Playgroud)