Android Kotlin:赋值后int_lives变量未更新,Quiz中始终为初始值1
问题分析
你的问题核心在于DataStore数据加载是异步的:
gameCurrencyManager.getLives.asLiveData().observe()的回调会在主线程空闲时触发,而你在onCreate中调用完setInGameCurrencyFromGameCurrencyManager()后立刻执行loadQuestion(),此时LiveData的回调还没执行,int_lives自然还是初始值1。- 日志中
tag_NumberOfLivesToBeAdded能打印出5,说明DataStore的数据确实能成功获取,但时机晚于loadQuestion()的执行。
另外,Delegates.notNull()报错是因为它要求变量在被使用前必须完成赋值,而你提前调用loadQuestion()时变量还未被赋值;lateinit不能用于Int这类基本数据类型,所以无法使用。
解决方案
方案1:在LiveData回调中触发Quiz初始化
确保只有当DataStore的数据加载完成后,才执行loadQuestion()逻辑:
class ActivityGame : AppCompatActivity() { var int_lives: Int = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_question_multiple_choice_question) gameCurrencyManager = gameCurrencyManager(this) setInGameCurrencyFromGameCurrencyManager() // 移除这里的loadQuestion()调用,等待LiveData回调后执行 } fun loadQuestion(){ Log.d("tag_NumberOfLives", int_lives.toString()) if(int_energyDrinksTotal <= 0){ // Message Dialog Box } } fun setInGameCurrencyFromGameCurrencyManager(){ gameCurrencyManager.getLives.asLiveData().observe(this) { int_lives = it Log.d("tag_NumberOfLivesToBeAdded", int_lives.toString()) textview_lives.setText("$int_lives", TextView.BufferType.EDITABLE) // 数据加载完成后初始化Quiz loadQuestion() } } }
如果后续生命值发生变化需要同步更新Quiz逻辑,也可以把loadQuestion()放在这个回调里,保证每次数据更新都能触发最新逻辑。
方案2:用协程同步获取DataStore数据
如果不想依赖LiveData回调,可直接用协程+suspend函数同步获取DataStore数据(前提是gameCurrencyManager.getLives返回Flow<Int>):
class ActivityGame : AppCompatActivity() { var int_lives: Int = 1 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_question_multiple_choice_question) gameCurrencyManager = gameCurrencyManager(this) // 用lifecycleScope确保协程跟随Activity生命周期 lifecycleScope.launch { // 同步获取Flow的第一个值(即当前存储的生命值) int_lives = gameCurrencyManager.getLives.first() textview_lives.setText("$int_lives", TextView.BufferType.EDITABLE) // 拿到数据后再初始化Quiz loadQuestion() // 如果需要监听后续生命值变化,可继续收集Flow gameCurrencyManager.getLives.collect { newLives -> int_lives = newLives textview_lives.setText("$newLives", TextView.BufferType.EDITABLE) // 可选:每次生命值变化时更新Quiz loadQuestion() } } } fun loadQuestion(){ Log.d("tag_NumberOfLives", int_lives.toString()) if(int_energyDrinksTotal <= 0){ // Message Dialog Box } } }
方案3:将int_lives改为LiveData
让Quiz逻辑直接观察生命值的变化,避免依赖普通变量的同步问题:
class ActivityGame : AppCompatActivity() { // 用LiveData存储生命值,默认值1 private val int_lives = MutableLiveData<Int>(1) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_question_multiple_choice_question) gameCurrencyManager = gameCurrencyManager(this) setInGameCurrencyFromGameCurrencyManager() // 观察生命值变化,触发Quiz逻辑 int_lives.observe(this) { lives -> textview_lives.setText("$lives", TextView.BufferType.EDITABLE) loadQuestion(lives) } } // 直接接收最新的生命值参数 fun loadQuestion(lives: Int){ Log.d("tag_NumberOfLives", lives.toString()) if(int_energyDrinksTotal <= 0){ // Message Dialog Box } } fun setInGameCurrencyFromGameCurrencyManager(){ gameCurrencyManager.getLives.asLiveData().observe(this) { int_lives.value = it Log.d("tag_NumberOfLivesToBeAdded", it.toString()) } } }
内容的提问来源于stack exchange,提问作者mi-ned32
相关产品推荐
相关产品推荐

