在 ViewModel 中使用 DataStore 无法正确保存和检索数据

问题描述 投票:0回答:1

我目前正在尝试将简单数据(PIN 码和恢复电子邮件)保存到数据存储中。这样我的应用程序就知道启动时的行为方式。我决定创建一个数据存储类来处理整个应用程序中的数据存储。我确信由于 toast 消息,这些函数会在适当的时间被调用。主要问题是,尽管完成了引脚设置阶段并看到引脚已更新,但引脚将始终保留值“教程”。

当前问题解决:

  • 似乎传递的上下文不是问题,因为每次启动时它似乎都是相同的。

LaunchActivity.kt

class LaunchActivity : AppCompatActivity() {


    private val dataModel by viewModels<LaunchVModel>()
    private var pin: String? = null
    override fun onCreate(savedInstanceState: Bundle?) {

        installSplashScreen().apply {
            setKeepOnScreenCondition {
                !dataModel.isReady.value
            }

            setOnExitAnimationListener {
            // code removed for brevity
            }
        }

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        if(pin == null) { // no pin option set, start w/ tutorial
            replaceFragment(TutorialFragment())
        }

        else if(pin == "tutorial") { // user chose not to have a pin
            switchActivity()
        }

        else { // user has a pin
            replaceFragment(PasscodeFragment())
        }

        dataModel.pin.observe(this) { // update the pin
            pin = dataModel.returnPin()
            Toast.makeText(this, "Pin val in View Model...$pin", Toast.LENGTH_SHORT).show()
        }
    }
}

基本数据

class BasicData (context: Context) {
    private val Context.dataStore : DataStore<Preferences> by preferencesDataStore(name = "LaunchSettings")
    private val dataStore = context.dataStore

    suspend fun set(key : String, given : String) {
        val dataStoreKey = stringPreferencesKey(key)
        dataStore.edit{ basics ->
            basics[dataStoreKey] = given
        }
    }

    suspend fun retrieve(key: String) : String? {
        val dataStoreKey = stringPreferencesKey(key)
        val preferences = dataStore.data.first()
        return preferences[dataStoreKey]
    }

}

视图模型

class LaunchVModel(application: Application): AndroidViewModel(application) {
    // needed for the pause on splash (launch) animation
    private val _isReady = MutableStateFlow(false)
    val isReady = _isReady.asStateFlow()
    private var dataStore = BasicData(application)
    var pin = MutableLiveData<String>()
    var email = MutableLiveData<String>()
    var skip = MutableLiveData<String>()

    // immediately execute the splash delay
    init {
        viewModelScope.launch {
            var temp = dataStore.retrieve("pin")
            if(temp != null) {
                pin.value = temp!!
                _isReady.value = true
            }
            else {
                pin.value = "tutorial"
                _isReady.value = true
            }
        }
    }

    fun returnPin() : String? {
        return pin.value.toString()
    }

    fun data(item: String) {
        viewModelScope.launch {
            dataStore.set("pin", item)
            pin.value = item
        }
    }
}
android kotlin android-viewmodel datastore
1个回答
0
投票

问题出在您的

dataStore.data.first()
方法中的
retrieve
。将方法更新为:

suspend fun retrieve(key: String) : String? {
        val dataStoreKey = stringPreferencesKey(key)
        return dataStore.data.map{
           it[dataStoreKey]
        }.firstOrNull()
    }

© www.soinside.com 2019 - 2024. All rights reserved.