저번 글에서 문제는 토스트 메시지가 프래그먼트가 기기 회전 등의 이유로 재생성될 때마다 다시 보이는 것이었다.
바로 본론으로 들어가보자.
Reset the game-finished event
보통, LiveData는 데이터 변경이 있을 때만 업데이트를 옵저버에게 전달한다.
이 행동의 예외 사항은 옵저버가 비활성 상태에서 활성 상태로 변경될 때도 업데이트를 수신한다는 것이다.
이것이 게임 종료에 대한 토스트가 반복적으로 발생하는 이유이다.
화면 회전 이후 GameFragment가 재생성되면 비활성에서 활성 상태로 변경되고, 옵저버는 기존 ViewModel에 다시 연결된다.
그리고, 데이터를 수신한다. 그럼 gameFinished 메소드가 다시 호출되고, 토스트가 표시된다.
GameViewModel안의 eventGameFinish 플래그를 초기화하여 이 이슈를 해결해보자.
1. GameViewModel에 game finished 이벤트를 초기화하기 위해 onGameFinishComplete 메소드를 추가한다.
/** Method for the game completed event **/
fun onGameFinishComplete() {
_eventGameFinish.value = false
}
2. GameFragment의 gameFinished 메소드 마지막에 onGameFinishComplete 메소드를 viewModel 객체에 호출한다.
(주석 처리된 문장들은 아직 잠시 두자)
private fun gameFinished() {
...
viewModel.onGameFinishComplete()
}
3. 앱을 실행하고 모든 단어를 넘긴다. 그 다음 기기를 회전시키면 토스트가 한 번만 보인다.
4. GameFragment의 gameFinished 메소드 내의 navigation 관련 코드를 주석 해제한다.
private fun gameFinished() {
Toast.makeText(activity, "Game has just finished", Toast.LENGTH_SHORT).show()
val action = GameFragmentDirections.actionGameToScore()
action.score = viewModel.score.value?:0
findNavController(this).navigate(action)
viewModel.onGameFinishComplete()
}
5. 앱을 다시 실행한다. 모든 단어가 끝나고 마지막 점수 화면으로 이동하는 것을 확인한다.
이렇게 되면 우리가 수정한 이 앱은 GameViewModel에서 프래그먼트에게
단어 리스트가 비어있다고 통신하기 위해 LiveData가 game-finished 이벤트를 발생시킨다.
(번역하기 애매한 문장이었다...)
'Android' 카테고리의 다른 글
Codelab으로 LiveData 알아보기 - 7. Add the Play Again Button (0) | 2023.05.01 |
---|---|
Codelab으로 LiveData 알아보기 - 6. Add LiveData to the ScoreViewModel (0) | 2023.04.28 |
Codelab으로 LiveData 알아보기 - 4. Add a game-finished event(1) (0) | 2023.04.25 |
종종 간과하는 문제 해결 에피소드(feat. Handler, Thread) (0) | 2023.04.24 |
구글 플레이 개발자 이름 주의 사항(오늘도 여전한 구글) (0) | 2023.03.27 |