Skip to content

Composables ​

PulseHost ​

kotlin
@Composable
fun <Broadcast : PulseBroadcast, Unicast : PulseUnicast> PulseHost(
    container: PulseContainer<Broadcast, Unicast>,
    content: @Composable (
        onRefresh: () -> Unit,
        onBroadcast: (Broadcast) -> Unit,
    ) -> Unit = { _, _ -> },
)

PulseContainer をこのサブツリーにスコープします。自身は UI を描画せず、役割は 2 つです。Container のキーを公開して、内側の PulseContent が container.refresh() に反応できるようにします。コンテンツブロックには onRefresh と onBroadcast を渡します。

アプリには複数置くことができます。デモでは、Container を所有する各 destination がそれぞれ自分の PulseHost を持っています。

パラメータ ​

パラメータ型説明
containerPulseContainer<Broadcast, Unicast>観測する Container
content@Composable (onRefresh, onBroadcast) -> Unit2 つのコールバックを受け取るコンテンツブロック

例 ​

kotlin
PulseHost(container = appContainer) { onRefresh, onBroadcast ->
    Column {
        Button(onClick = { onBroadcast(AppBroadcast.Sync) }) {
            Text("Sync All")
        }
        Button(onClick = { onRefresh() }) {
            Text("Refresh View")
        }
        MyContent(viewModel = myViewModel)
    }
}

PulseContent ​

kotlin
@Composable
fun <
    State : PulseState,
    Action : PulseAction,
    Event : PulseEvent,
    Broadcast : PulseBroadcast,
    Unicast : PulseUnicast,
>
PulseContent(
    viewModel: PulseViewModel<State, Action, Event, Broadcast, Unicast>,
    onEvent: (Event) -> Unit = {},
    content: @Composable (State, (Action) -> Unit) -> Unit = { _, _ -> },
)

PulseViewModel を観測し、コンテンツブロックに状態と Action のディスパッチャを渡します。インスタンスを最初に観測したときに onSetup() を実行しますが、キャンセルは行いません。

1 つのインスタンスは、同時に 1 つの PulseContent からだけ観測してください。event は単一消費者のチャネルです。

パラメータ ​

パラメータ型説明
viewModelPulseViewModel<State, Action, Event, Broadcast, Unicast>観測する ViewModel
onEvent(Event) -> UnitViewModel が発行した一度きりの副作用ごとに呼ばれる
content@Composable (State, (Action) -> Unit) -> Unit現在の状態を描画する。Action を送るためのディスパッチャを受け取る

ライフサイクルの挙動 ​

  • PulseContent は ViewModel をキャンセルしない。後始末は所有者の責務
  • LaunchedEffect(viewModel) が event を収集する。届け先は常に最新の onEvent
  • onSetup() は、PulseContent が ViewModel を最初に観測したときに一度だけ実行される
  • 所有する ViewModelStoreOwner が破棄されると、スコープがキャンセルされる
  • コンポジションを離れて戻ってきても(別のナビゲーション destination がルートを覆う場合など)onSetup() は繰り返されない
  • PulseHost の内側では key(containerKey) で包まれる。refresh() で作り直される

例 ​

kotlin
PulseContent(
    viewModel = counterViewModel,
    onEvent = { event ->
        when (event) {
            is CounterEvent.ShowMessage ->
                scope.launch { snackbarHostState.showSnackbar(event.message) }
        }
    },
) { state, onAction ->
    Column {
        Text("Count: ${state.count}")
        Button(onClick = { onAction(CounterAction.Increment) }) {
            Text("+")
        }
    }
}

Apache 2.0 License の下で公開されています。