November 03, 2021
일반적인 수명주기에서 더 복잡한 작업을 수행할 때 Side Effects를 필요로 합니다.
Composable 내에서 suspend 함수를 호출할 때 사용
Composable 외부에서 코루틴 실행할 때 사용
값이 변경되더라도 recomposition되지 않는 효과에서 값 참조
@Composable
fun LandingScreen(onTimeout: () -> Unit) {
// This will always refer to the latest onTimeout function that
// LandingScreen was recomposed with
val currentOnTimeout by rememberUpdatedState(onTimeout)
// Create an effect that matches the lifecycle of LandingScreen.
// If LandingScreen recomposes, the delay shouldn't start again.
LaunchedEffect(true) {
delay(SplashWaitTimeMillis)
currentOnTimeout()
}
/* Landing screen content */
}
Composition을 종료한 뒤 clear해야하는 부수 효과에 적용합니다.
DisposableEffect(lifecycleOwner) {
// Create an observer that triggers our remembered callbacks
// for sending analytics events
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START) {
currentOnStart()
} else if (event == Lifecycle.Event.ON_STOP) {
currentOnStop()
}
}
// Add the observer to the lifecycle
lifecycleOwner.lifecycle.addObserver(observer)
// When the effect leaves the Composition, remove the observer
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
Compose State를 비 Compose 코드에서 구독
비 Compose 를 Compose State로 변환
@Composable
fun loadNetworkImage(
url: String,
imageRepository: ImageRepository
): State<Result<Image>> {
// Creates a State<T> with Result.Loading as initial value
// If either `url` or `imageRepository` changes, the running producer
// will cancel and will be re-launched with the new keys.
return produceState(initialValue = Result.Loading, url, imageRepository) {
// In a coroutine, can make suspend calls
val image = imageRepository.load(url)
// Update State with either an Error or Success result.
// This will trigger a recomposition where this State is read
value = if (image == null) {
Result.Error
} else {
Result.Success(image)
}
}
}
State 객체를 다른 State 객체에서 사용할 때
val todoTasks = remember { mutableStateListOf<String>() }
// Calculate high priority tasks only when the todoTasks or
// highPriorityKeywords change, not on every recomposition
val highPriorityTasks by remember(todoTasks, highPriorityKeywords) {
derivedStateOf {
todoTasks.filter { it.containsWord(highPriorityKeywords) }
}
}
State를 Flow로 변환