尝试更改观察者内部的 MutableLiveData 值时应用程序没有响应
The app not responding when try to change MutableLiveData value inside observer
在这个应用“猜一猜”游戏中,我试图检测当用户到达 wordList 末尾时游戏何时结束,在 GameViewModel 中 _eventGameFinish val 负责
GameViewModel
class GameViewModel : ViewModel() {
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish : LiveData<Boolean>
get()= _eventGameFinish
// The list of words - the front of the list is the next word to guess
private lateinit var wordList: MutableList<String>
init {
Log.i("GameViewModel", "GameViewModel created!")
resetList()
nextWord()
_score.value = 0
_eventGameFinish.value = false
}
/**
* Resets the list of words and randomizes the order
*/
private fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}
/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
_eventGameFinish.value = true
} else {
_word.value = wordList.removeAt(0)
}
}
/** Methods for buttons presses **/
fun onSkip() {
_score.value = score.value?.minus(1)
nextWord()
}
fun onCorrect() {
_score.value = score.value?.plus(1)
nextWord()
}
fun onGameFinishComplete(){
_eventGameFinish.value = false
}
override fun onCleared() {
super.onCleared()
Log.i("GameViewModel", "GameViewModel destroyed")
}
}
在 GameFragment 中,我在 eventGameFinish
上观察,然后调用 gameViewModel.onGameFinishComplete()
以在片段中仅执行一次操作
这里是 GameFragment class
class GameFragment : Fragment() {
private lateinit var gameViewModel: GameViewModel
private lateinit var binding: GameFragmentBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
)
Log.i("GameViewModelOf", "GameViewModelOf")
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
binding.correctButton.setOnClickListener {
gameViewModel.onCorrect()
}
binding.skipButton.setOnClickListener {
gameViewModel.onSkip()
}
gameViewModel.score.observe(viewLifecycleOwner, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
gameViewModel.word.observe(viewLifecycleOwner, Observer { newWord ->
binding.wordText.text = newWord
})
gameViewModel.eventGameFinish.observe(viewLifecycleOwner, Observer { eventGameFinish ->
if (eventGameFinish) this.gameFinished()
gameViewModel.onGameFinishComplete()
})
return binding.root
}
/**
* Called when the game is finished
*/
private fun gameFinished() {
// val action = GameFragmentDirections.actionGameToScore(gameViewModel.score.value ?: 0)
// findNavController(this).navigate(action)
Toast.makeText(this.activity, "Game finished", Toast.LENGTH_SHORT).show()
}
}
问题出在这一行 gameViewModel.onGameFinishComplete()
当我在 Observer 块中调用方法时 运行 应用程序没有任何异常响应,如果我删除了这个方法调用,应用程序是工作正常,但我无法在到达 wordList
末尾时更改 eventGameFinish
的值
您正在观察“eventGameFinish”,如果它是真的,它将调用 gameFinished() 方法和 onGameFinishComplete() 代码将新值设置为 eventGameFinish.so 观察者将再次观察到新值。现在它是假的,它将一次又一次地调用 gameViewModel() 并设置 false.that 是你收到 ANR 的原因。
因此仅当实时数据值为 true.OR 时才调用方法,在游戏结束后使用单独的 MutableLiveData 数据设置值。
if (eventGameFinish)
{
this.gameFinished()
gameViewModel.onGameFinishComplete()
}
在这个应用“猜一猜”游戏中,我试图检测当用户到达 wordList 末尾时游戏何时结束,在 GameViewModel 中 _eventGameFinish val 负责
GameViewModel
class GameViewModel : ViewModel() {
// The current word
private val _word = MutableLiveData<String>()
val word: LiveData<String>
get() = _word
// The current score
private val _score = MutableLiveData<Int>()
val score: LiveData<Int>
get() = _score
private val _eventGameFinish = MutableLiveData<Boolean>()
val eventGameFinish : LiveData<Boolean>
get()= _eventGameFinish
// The list of words - the front of the list is the next word to guess
private lateinit var wordList: MutableList<String>
init {
Log.i("GameViewModel", "GameViewModel created!")
resetList()
nextWord()
_score.value = 0
_eventGameFinish.value = false
}
/**
* Resets the list of words and randomizes the order
*/
private fun resetList() {
wordList = mutableListOf(
"queen",
"hospital",
"basketball",
"cat",
"change",
"snail",
"soup",
"calendar",
"sad",
"desk",
"guitar",
"home",
"railway",
"zebra",
"jelly",
"car",
"crow",
"trade",
"bag",
"roll",
"bubble"
)
wordList.shuffle()
}
/**
* Moves to the next word in the list
*/
private fun nextWord() {
//Select and remove a word from the list
if (wordList.isEmpty()) {
_eventGameFinish.value = true
} else {
_word.value = wordList.removeAt(0)
}
}
/** Methods for buttons presses **/
fun onSkip() {
_score.value = score.value?.minus(1)
nextWord()
}
fun onCorrect() {
_score.value = score.value?.plus(1)
nextWord()
}
fun onGameFinishComplete(){
_eventGameFinish.value = false
}
override fun onCleared() {
super.onCleared()
Log.i("GameViewModel", "GameViewModel destroyed")
}
}
在 GameFragment 中,我在 eventGameFinish
上观察,然后调用 gameViewModel.onGameFinishComplete()
以在片段中仅执行一次操作
这里是 GameFragment class
class GameFragment : Fragment() {
private lateinit var gameViewModel: GameViewModel
private lateinit var binding: GameFragmentBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate view and obtain an instance of the binding class
binding = DataBindingUtil.inflate(
inflater,
R.layout.game_fragment,
container,
false
)
Log.i("GameViewModelOf", "GameViewModelOf")
gameViewModel = ViewModelProvider(this).get(GameViewModel::class.java)
binding.correctButton.setOnClickListener {
gameViewModel.onCorrect()
}
binding.skipButton.setOnClickListener {
gameViewModel.onSkip()
}
gameViewModel.score.observe(viewLifecycleOwner, Observer { newScore ->
binding.scoreText.text = newScore.toString()
})
gameViewModel.word.observe(viewLifecycleOwner, Observer { newWord ->
binding.wordText.text = newWord
})
gameViewModel.eventGameFinish.observe(viewLifecycleOwner, Observer { eventGameFinish ->
if (eventGameFinish) this.gameFinished()
gameViewModel.onGameFinishComplete()
})
return binding.root
}
/**
* Called when the game is finished
*/
private fun gameFinished() {
// val action = GameFragmentDirections.actionGameToScore(gameViewModel.score.value ?: 0)
// findNavController(this).navigate(action)
Toast.makeText(this.activity, "Game finished", Toast.LENGTH_SHORT).show()
}
}
问题出在这一行 gameViewModel.onGameFinishComplete()
当我在 Observer 块中调用方法时 运行 应用程序没有任何异常响应,如果我删除了这个方法调用,应用程序是工作正常,但我无法在到达 wordList
eventGameFinish
的值
您正在观察“eventGameFinish”,如果它是真的,它将调用 gameFinished() 方法和 onGameFinishComplete() 代码将新值设置为 eventGameFinish.so 观察者将再次观察到新值。现在它是假的,它将一次又一次地调用 gameViewModel() 并设置 false.that 是你收到 ANR 的原因。
因此仅当实时数据值为 true.OR 时才调用方法,在游戏结束后使用单独的 MutableLiveData 数据设置值。
if (eventGameFinish)
{
this.gameFinished()
gameViewModel.onGameFinishComplete()
}