我正在尝试将生命数量纳入测验。似乎发生的情况是,首选项数据存储中的生命数存储到变量中,但当在测验中实际使用它时,它似乎与初始变量值 1 没有任何变化。
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()
}
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)
}
}
}
这导致“tag_NumberOfLivesToBeAdded”打印出 5,正如预期的那样;然而,当谈到“tag_NumberOfLives”时,一旦测验开始运行,结果就是 1。
我尝试将变量 int_lives 设置为 Delegates.notNull() 但这导致了异常,但因为我无法将变量设置为 Lateinit。
观察实时数据是异步的,因此在调用
loadQuestion()
函数之后,将来会稍微设置变量。
快速但肮脏的解决方案是通过在流程上使用
runBlocking
和 first()
来读取首选项。您不应该像这样在主线程上读取文件,但您的首选项文件可能很小,并且不会面临明显冻结应用程序的风险。仅当您只需要在每次活动启动时读取一次该值(而不是每次向首选项写入新值时)时,这样做才有意义,这里似乎就是这种情况。
fun setInGameCurrencyFromGameCurrencyManager(){
int_lives = runBlocking {
gameCurrencyManager.getLives.first()
}
Log.d("tag_NumberOfLivesToBeAdded", int_lives.toString())
textview_lives.setText("$int_lives", TextView.BufferType.EDITABLE)
}
更正确的方法是等待值到达然后才开始使用它:
class ActivityGame : AppCompatActivity() {
var int_lives: Int = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
int_lives = gameCurrencyManager.getLives.first()
startGame()
}
}
private fun startGame() {
setContentView(R.layout.activity_question_multiple_choice_question)
textview_lives.setText("$int_lives", TextView.BufferType.EDITABLE)
loadQuestion()
}
//…
}
如果您认为数据需要一段时间才能加载,您可以在启动协程之前设置一个显示某种加载屏幕的内容视图。