이전에 정리했던 생명주기 글을 보면 됨!
initial Composition
: 처음 호출된 Composable 상태
Recomposition
: 상태가 변경됨에 따라 UI 가 다시 그려지는 상태
Decomposition
: Composable 이 파괴 되는 상태`
Recomposition
은 상태가 변경되었을 수 있는 구성 가능한 함수를 Compose에서 다시 실행하고 업데이트된 UI를 만드는 것을 의미 -> 컴포지션은 이러한 변경사항을 반영하도록 업데이트됨Recomposition
을 추적하고 트리거하려면 상태가 변경된 시점을 알아야 함State
또는 MutableState
이면 객체의 상태를 추적할 수 있음 State
: 변경할 수 없으며 읽기만 가능MutableState
: 변경 가능하며 읽기 및 쓰기를 허용Recomposition
이 일어날 때 변경된 상태를 저장하기 위해(값을 유지하고 재사용하도록) remember
를 사용remember
은 구성 변경 중에는 이 상태를 유지하지 않음rememberSaveable
을 사용https://velog.io/@minchae75/Android-안드로이드-앱-아키텍처-App-Architecture
value
속성은 현재 상태 값을 반영asStateFlow()
: 변경 가능 상태 흐름을 읽기 전용 상태 흐름으로 만듦implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
ui
패키지에 GameViewModel
클래스 추가ui
패키지에서 GameUiState
라는 상태 UI의 모델 클래스를 추가/* GameViewModel.kt */
class GameViewModel : ViewModel() { // ViewModel 클래스 확장해서 사용
// Game UI state, StateFlow 사용
private val _uiState = MutableStateFlow(GameUiState()) // ViewModel 내부에서만 값에 접근 가능
val uiState: StateFlow<GameUiState> = _uiState.asStateFlow() // asStateFlow()는 이 변경 가능 상태 흐름을 읽기 전용 상태 흐름으로 만듦
// 임의의 단어를 선택하고 단어의 글자를 섞는 도우미 메서드를 추가
// Set of words used in the game
private var usedWords: MutableSet<String> = mutableSetOf()
private lateinit var currentWord: String // 글자가 섞인 현재 단어를 저장
init {
resetGame()
}
// 목록에서 임의 단어를 선택하여 글자를 섞는 메서드
private fun pickRandomWordAndShuffle(): String {
// Continue picking up a new random word until you get one that hasn't been used before
currentWord = allWords.random()
if (usedWords.contains(currentWord)) {
return pickRandomWordAndShuffle()
} else {
usedWords.add(currentWord)
return shuffleCurrentWord(currentWord)
}
}
// String을 받아서 순서가 섞인 String을 반환하여 현재 단어의 순서를 섞는 도우미 메서
private fun shuffleCurrentWord(word: String): String {
val tempWord = word.toCharArray()
// Scramble the word
tempWord.shuffle()
while (String(tempWord).equals(word)) {
tempWord.shuffle()
}
return String(tempWord)
}
// 게임 초기화
// usedWords 세트에 있는 모든 단어를 지우고 _uiState를 초기화
// pickRandomWordAndShuffle()을 사용하여 currentScrambledWord의 새 단어를 선택
fun resetGame() {
usedWords.clear()
_uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle())
}
}
/* GameUiState.kt */
data class GameUiState(
val currentScrambledWord: String = "" // 글자가 섞인 현재 단어를 위한 변수를
)
GameScreen.kt
파일에서 ViewModel 인스턴스를 UI로(즉, GameViewModel
에서 GameScreen()
으로) 전달GameScreen()
에서 collectAsState()
를 통해 ViewModel 인스턴스를 사용하여 uiState에 접근collectAsState()
: StateFlow
에서 값을 수집하고 State
를 통해 최신 값을 나타냄StateFlow.value
는 초깃값으로 사용StateFlow
에 새 값이 게시될 때마다 반환된 State
가 업데이트되어 State.value
가 사용된 모든 경우에서 재구성이 이루어짐/* GameScreen 컴포저블 */
@Composable
fun GameScreen(
gameViewModel: GameViewModel = viewModel()
) {
// uiState 값이 변경될 때마다 gameUiState 값을 사용하여 구성 가능한 함수가 재구성되도록 함
val gameUiState by gameViewModel.uiState.collectAsState()
}
GameLayout(
currentScrambledWord = gameUiState.currentScrambledWord,
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(mediumPadding)
)
/* GameLayout 컴포저블 */
@Composable
fun GameLayout(
currentScrambledWord: String, // 인수 추가
modifier: Modifier = Modifier
) {
Column(
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
//...
Text(
text = currentScrambledWord,
style = typography.displayMedium
)
//...
}
}
여기까지 하고 앱을 실행 하면 글자가 섞인 단어가 표시됨
https://github.com/MinchaeKwon/AndroidCompose/tree/master/Chapter4/Unscramble