Как вызвать перекомпоновку при изменении родительских данных с помощью CompositionLocal

когда я использую CompositionLocal, я получаю данные от родителя и изменяю их, но обнаружил, что это не вызовет перекомпоновку потомков.

Я успешно изменил данные, что подтверждается тем, что когда я добавляю дополнительное состояние в дочерний компонент, а затем изменяю его, чтобы инициировать перекомпоновку, я могу получить новые данные.

Кто-нибудь может мне помочь?

Добавить

код, как показано ниже

      
data class GlobalState(var count: Int = 0)

val LocalAppState = compositionLocalOf { GlobalState() }

@Composable
fun App() {
    CompositionLocalProvider(LocalAppState provides GlobalState()) {
        CountPage(globalState = LocalAppState.current)
    }
}

@Composable
fun CountPage(globalState: GlobalState) {
    // use it request recomposition worked
//    val recomposeScope = currentRecomposeScope
    BoxWithConstraints(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxSize()
            .clickable {
                globalState.count++
//                recomposeScope.invalidate()

            }) {
        Text("count ${globalState.count}")
    }
}

Я нашел обходной путь, использующий Чтобы заставить перекомпоновку, может быть, есть лучший способ, и, пожалуйста, скажите мне.

3 ответа

Композиция "местная" здесь - отвлекающий маневр. С GlobalScopeне наблюдаемый состав не уведомляется о том, что он изменился. Самое простое изменение - изменить определение GlobalState к,

      class GlobalState(count: Int) {
   var count by mutableStateOf(count)
}

Это автоматически уведомит compose о том, что значение count изменилось.

Я не уверен, почему вы используете compositionLocalOf этим способом.

Вы можете использовать что-нибудь попроще:

      data class GlobalState(var count: Int = 0)

@Composable
fun App() {

    var counter by remember { mutableStateOf(GlobalState(0)) }
    CountPage(
        globalState = counter,
        onUpdateCount = {
                counter = counter.copy(count = counter.count +1)
            }
        )
}

@Composable
fun CountPage(globalState: GlobalState, onUpdateCount: () -> Unit) {
   
    BoxWithConstraints(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxSize()
            .clickable (
                onClick = onUpdateCount
            )) {
        Text("count ${globalState.count}")
    }
}

Вы можете объявить свои данные как и либо предоставить отдельно геттер и сеттер, либо просто предоставить MutableStateобъект напрямую.

      internal val LocalTest = compositionLocalOf<Boolean> { error("lalalalalala") }
internal val LocalSetTest = compositionLocalOf<(Boolean) -> Unit> { error("lalalalalala") }

@Composable
fun TestProvider(content: @Composable() () -> Unit) {
  val (test, setTest) = remember { mutableStateOf(false) }

  CompositionLocalProvider(
    LocalTest provides test,
    LocalSetTest provides setTest,
  ) {
    content()
  }
}

Внутри дочернего компонента вы можете сделать:

      @Composable
fun Child() {
  val test = LocalTest.current
  val setTest = LocalSetTest.current

  Column {
    Button(onClick = { setTest(!test) }) {
      Text(test.toString())
    }
  }
}
Другие вопросы по тегам