컴포저블의 범위에서 정지 함수 실행
컴포지션 인식 범위를 확보하여 컴포저블 외부에서 코루틴 실행
값이 변경되는 경우 다시 시작되지 않아야 하는 효과에서 값 참조
정리가 필요한 효과
Compose 상태를 비 Compose 코드에 게시
비 Compose 상태를 Compose 상태로 변환
하나 이상의 상태 객체를 다른 상태로 변환
Compose의 상태를 Flow로 변환2
@Composable
fun MyScreen(
state: UiState<List<Movie>>,
scaffoldState: ScaffoldState = rememberScaffoldState()
) {
if (state.hasError) {
LaunchedEffect(scaffoldState.snackbarHostState) {
scaffoldState.snackbarHostState.showSnackbar(
message = "Error message",
actionLabel = "Retry message"
)
}
Scaffold(scaffoldState = scaffoldState) {
}
}
}
@Composable
fun MoviesScreen(scaffoldState: ScaffoldState =
rememberScaffoldState()) {
val scope = rememberCoroutineScope()
Scaffold(scaffoldState = scaffoldState) {
Column {
Button(
onClick = {
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("Something
happened!")
}
}
) {
}
Text("Press me")
}
}
}
@Composable
fun LandingScreen(onTimeout: () -> Unit) {
val currentOnTimeout by rememberUpdatedState(onTimeout)
LaunchedEffect(true) {
delay(SplashWaitTimeMillis)
currentOnTimeout()
}
}
@Composable
fun HomeScreen(
lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
onStart: () -> Unit,
onStop: () -> Unit
) {
val currentOnStart by rememberUpdatedState(onStart)
val currentOnStop by rememberUpdatedState(onStop)
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_START) {
currentOnStart()
} else if (event == Lifecycle.Event.ON_STOP) {
currentOnStop()
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
}
@Composable
fun rememberAnalytics(user: User): FirebaseAnalytics {
val analytics: FirebaseAnalytics = remember {
/* ... */
}
SideEffect {
analytics.setUserProperty("userType", user.userType)
}
return analytics
}
@Composable
fun loadNetworkImage(
url: String,
imageRepository: ImageRepository
): State<Result<Image>> {
return produceState<Result<Image>>(initialValue = Result.Loading, url, imageRepository) {
val image = imageRepository.load(url) // suspend call
value = if (image == null) {
Result.Error
} else {
Result.Success(image)
}
}
}
@Composable
fun TodoList(highPriorityKeywords: List<String> = listOf("Review", "Unblock", "Compose")) {
val todoTasks = remember { mutableStateListOf<String>() }
val highPriorityTasks by remember(highPriorityKeywords) {
derivedStateOf { todoTasks.filter { it.containsWord(highPriorityKeywords) } }
}
Box(Modifier.fillMaxSize()) {
LazyColumn {
items(highPriorityTasks) { /* ... */ }
items(todoTasks) { /* ... */ }
}
}
}
val listState = rememberLazyListState()
LazyColumn(state = listState) {
// ...
}
LaunchedEffect(listState) {
snapshotFlow { listState.firstVisibleItemIndex }
.map { index -> index > 0 }
.distinctUntilChanged()
.filter { it == true }
.collect {
MyAnalyticsService.sendScrolledPastFirstItemEvent()
}
}