美文网首页
Jetpack Compose 中的副作用

Jetpack Compose 中的副作用

作者: BlueSocks | 来源:发表于2022-08-23 13:57 被阅读0次

启动效果

让我们在可组合对象中运行挂起函数。当LaunchedEffect进入Composition时,它会启动一个协程,并将代码块作为参数传递。如果它有多个键和一个变化,则现有的协程将被取消,并在新的协程中启动新的挂起功能。

class HomeScreenViewModel : ViewModel() {
    private val _uiEvent = MutableSharedFlow<UiEvent>(0)
    val uiEvent: SharedFlow<UiEvent> = _uiEvent.asSharedFlow()
}

@Composable
fun HomeScreen(
    viewModel: HomeScreenViewModel = viewModel(),
) {
    val scaffoldState = rememberScaffoldState()

    LaunchedEffect(key1 = true) {
        viewModel.uiEvent.collect { event ->
            when (event) {
                is UiEvent.SnackBar -> {
                    scaffoldState.snackbarHostState.showSnackbar(
                        "SnackBar"
                    )
                }
            }
        }
    }
}

在上面的代码中,我们collects从 viewModel 启动了一个 uiEvents 的协程,当收集到的事件是 a 时,UiEvent.SnackBar我们会显示一个小吃店。

副作用

每次成功的组合都会调用它,如果组合失败,则不会执行此代码块

如果没有SideEffect,则timer++不会触发重组,因为它在重组时发生了更改,并且它会通知您启动调用应该发生在 aLaunchedEffect而不是composition内。

@Composable
fun Timer() {

    val coroutineScope = rememberCoroutineScope()

    var timer by remember {
        mutableStateOf(0)
    }

    timer++
    coroutineScope.launch {
        delay(1000)
    }

    Text(text = timer.toString())
}

有了SideEffect,timer++就会触发重组。这将创建一个计时器循环,您也将摆脱启动错误。

一次性效果

用于检测DisposableEffect键是否更改的取消,可组合项需要处理(进行清理)。

例如,我们希望在用户看不到应用程序时停止计时器。

@Composable
fun Timer(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    timer: Int,
    onStartTimer: () -> Unit,
    onStopTimer: () -> Unit,
) {
    DisposableEffect(key1 = lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_START) {
                onStartTimer()
            } else if (event == Lifecycle.Event.ON_STOP) {
                onStopTimer()
            }
        }

        lifecycleOwner.lifecycle.addObserver(observer)

        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    Text(text = timer.toString())
}

记住协程作用域

让我们在可组合之外启动一个协程,但其作用域是一旦离开组合就会自动取消。此外,您可以在需要手动控制一个或多个协程的生命周期时使用它,例如,显示一个ModalBottomSheet.

@Composable
fun MyScreen(
    modalBottomSheetState: ModalBottomSheetState,
) {
    // Creates a CoroutineScope bound to the MyScreen's lifecycle
    val scope = rememberCoroutineScope()

    ModalBottomSheetLayout(
        sheetContent = {
            /* ... */
        }
    ) {
        Button(
            onClick = {
                // Creates a new coroutine to show 
                // the modal bottom sheet
                scope.launch {
                    modalBottomSheetState.show()
                }
            }
        ) {
            Text(text = "Click me")
        }
    }
}

记住更新状态

它保证我们总是得到最新的状态变量变化。

@Composable
fun Timer(
    timer: Int
) {
    val updatedTimer by rememberUpdatedState(timer)

    LaunchedEffect(key1 = Unit) {
        delay(1000L)
        Log.d("Track", "$updatedTimer")
    }
}

生产状态

将非 Compose 状态转换为Compose状态,并启动协程。

@Composable
fun Screen() {
    val counter: State<Int> = produceState(initialValue = 0) {
        delay(200L)
        value = 4
    }

    Text(text = "${counter.value}")
}

在上面的代码中,我们生成了 aState<Int>并启动了一个协程,在其中添加了一个延迟,之后,我们为 counter 分配了一个新值

派生状态

当某个状态从其他状态对象计算或派生时使用。每当计算中使用的状态之一发生更改时,这将触发。

@Composable
fun ReceiptList(filter: String) {
    val receipts = remember {
        mutableStateListOf<String>()
    }

    val filteredReceipts by remember(filter) {
        derivedStateOf {
            receipts.filter {
                it.contains(filter)
            }
        }
    }

    LazyColumn {
        items(filteredReceipts) { /* ... */ }
        items(receipts) { /* ... */ }
    }
}

在上面的代码中,derivedStateOf保证每当收据发生变化时,都会进行filteredReceipts 计算并更新 UI。如果过滤器值发生变化,remember 块将被执行并创建一个新的派生状态对象。

快照流

它用于将Compose 状态对象转换为冷Flow。

@Composable
fun ReceiptList(
    showFloatingActionButton: () -> Unit
) {
    val lazyListState = rememberLazyListState()

    LaunchedEffect(key1 = lazyListState) {
        snapshotFlow { lazyListState.firstVisibleItemIndex }
            .collect {
                if (it == 0) {
                    showFloatingActionButton()
                }
            }
    }
}

在上面的代码中,如果lazyListState.firstVisibleItemIndex为 0,我们将显示FAB。

我希望这篇文章能让你对Jetpack Compose Side-effects有一个基本的了解。

来源:https://daniatitienei.hashnode.dev/side-effects-in-jetpack-compose

相关文章

网友评论

      本文标题:Jetpack Compose 中的副作用

      本文链接:https://www.haomeiwen.com/subject/qxlggrtx.html