mutableStateOf(value)remember { mutableStateOf(...) } 또는 rememberSaveable { ... } 형태var count by mutableStateOf(0)MutableStateFlow(value)collectAsState()로 구독하면 State으로 값이 변경. 이후 값이 변경될 때 재구성collectAsState() 사용하여 State형태로 바꾼 후 위임 사용 가능MutableSharedFlow(replay = 0, extraBufferCapacity=0)emit()과 tryEmit()존재emit()는 suspend이지만 tryEmit()는 즉시 반환하여 버퍼가 꽉 차면 실패emit(), 유실돼도 되는 이벤트에는 tryEmit() 사용LaunchedEffect(Unit) {
viewModel.events.collect { event -> ... }
}| 항목 | State | StateFlow | SharedFlow |
|---|---|---|---|
| 제공처 | Compose | Coroutine | Coroutine |
| 초기화 | mutableStateOf() | MutableStateFlow() | MutableSharedFlow() |
| 주사용처 | Composable 내부 상태 | UI와 상태 공유 (주로 ViewModel → UI) | 이벤트/신호 전달 (주로 ViewModel → UI) |
| 비동기 스트림 | 부적합 | 적합 | 적합 |
| 재구성 | 값 변경 시 자동으로 Composable 재구성 | 자체로는 재구성 불가 → collectAsState()로 State로 변환 후 재구성 | 자체로는 재구성 불가 → collectAsState() 또는 collectAsStateWithLifecycle()로 반영 |
| 단일/복합 데이터 | 단일 데이터에 적합 | 단일 현재 상태에 적합 | 단발성 이벤트/여러 이벤트 흐름에 적합 |
| 속성 위임 | 가능 (by) | 가능 (by는 State<T>에만 직접 가능) | 불가능 (State<T>로 변환해야 by 가능) |
| 스레드 안정성 | UI 스레드에서만 사용 권장 | 안정적 | 안정적 |
| 초기값 유지 | 유지 가능 | 유지 가능 (ViewModel 등과 사용 시 유지) | 기본적으로 초기값 없음(이벤트 중심), replay로 최근 값 재전달 가능 |
| 값 개념 | 현재 값 | 현재 값이 항상 존재 | 방출된 이벤트들 (현재값 개념 없음) |
| 초기값 필요 여부 | 필요 | 필요 | 불필요 |
| 최신 값 접근 | state.value | stateFlow.value | 불가(현재값 없음) |
| 구독 시작 시 동작 | 즉시 현재값 사용 | 즉시 현재값 1개 받음 | 기본은 아무것도 못 받음 (replay 설정 시 최근 이벤트 수신) |
| 주요 옵션 | - | - | replay, extraBufferCapacity, onBufferOverflow |
| 대표 용도 예시 | 텍스트 입력, 토글 상태 | 화면 상태, 로딩/데이터/에러 상태 | 토스트, 네비게이션, 스낵바, 1회성 메시지, 클릭 이벤트 전달 |