アプリ開発備忘録

PlayStationMobile、Android、UWPの開発備忘録

【Compose】movableContentOfの挙動を調べて見たらUIが更新されない

不具合である事が確認できました。
https://issuetracker.google.com/issues/270656235

movableContentOfとは

movableContentOf1.2.0-alpha03 で追加されたAPIです。
https://developer.android.com/jetpack/androidx/releases/compose-ui#1.2.0-alpha03

Compose Componentの作成ガイドラインで登場し、知りました。
https://github.com/androidx/androidx/blob/24310ca1c317aa88f990bd8aa3d2b4cba5b20588/compose/docs/compose-component-api-guidelines.md#lifecycle-expectations-for-slot-parameters

動作確認

引数のComposable関数で、Composable関数内のrememberを保持してコードの配置を変更することができます。

@Composable
fun MovableContent(
    isRow: Boolean,
    content: @Composable () -> Unit,
) {
    val movableContent = remember(content) { movableContentOf(content) }

    if (isRow) {
        Row {
            Text("Row")
            movableContent()
        }
    } else {
        Column {
            Text("Column")
            movableContent()
        }
    }
}

カウントアップできるボタンがあります。ボタンでRowとColumnを切り替えられます。movableContentOfにより、countの部分のrememberが保持されます。

Column {
    var isRow by remember { mutableStateOf(false) }
    MovableContent(isRow = isRow) {
        var count by remember { mutableStateOf(0) }

        Button(onClick = { count++ }) {
            Text(text = count.toString())
        }
    }

    Button(
        onClick = {
            isRow = !isRow
        },
    ) {
        Text("Button")
    }
}

しかし、ボタンを押してRowとColumnを切り替えると、ボタンを押しても表示が更新されなくなります。しかし、SideEffectは呼ばれており、変数も更新されていることは確認できました。

これが意図された挙動で、意図していない使い方なのか、使い方が間違っているのかは不明です。
尚、Composeコンパイラのバージョンは1.4.7です。