Состояние обновления вне составной функции. (Составить Jetpack)

Я пытаюсь реализовать сокращение с помощью Jetpack compose. Сценарий выглядит следующим образом: - У меня есть список, в котором мне нужно отображать данные в составной функции.

      @Composable
fun CreateListView(text: String) {
 val listdata = state { store.state }

    LazyColumn {
     //some listview code here
    }
}

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

          // activity page outside composable
private fun storeSubscription(){
    viewModel.storeSubscription = store.subscribe {

        when (store.state) {
            store.state = // list data from some source
        }
    }
}

Можно ли обновить составной объект, как указано выше, вне функции и без отправки какого-либо параметра. Поскольку redux store является глобальным, я думаю, он должен работать.

4 ответа

Решение

Попробуйте что-нибудь вроде,

      @Composable
fun <T> Store<T>.asState(): State<T> {
   val result = remember { mutableStateOf(store.state) }
   DisposableEffect {
       val unsubscribe = store.subscribe {
           result.value = store.state
       }
       onDispose { unsubscribe() }
   }
   return result
}

@Composable
fun CreateListView(text: String) {
    val listdata by store.asState()

    LazyColumn {
     //some listview code here
    }
}

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

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

Вы можете использовать MutableLiveData вне составной функции. Используйте visibleAsState() в компонуемых для перекомпоновки при изменении данных.

      private val myLive = MutableLiveData<String>()

fun nonComposableScope(){
  myLive.postValue("hello")
}

@Composable
fun MyScreen(textLive:LiveData<String>){
  val text: String? by textLive.observeAsState()
  // use text here
}

Вы можете просто использовать лямбду так:

(Пример из приложения, над которым я работаю.)

      @OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RumbleSearchResult(rumbleSearchResult: RumbleSearchResult, onClick: () -> Unit) {
    ListItem(
        headlineText = {
            rumbleSearchResult.title?.let { title ->
                Text(title)
            }
        },

        supportingText = {
            rumbleSearchResult.channel.let { creator ->
                val text = when {
                    rumbleSearchResult.views > 0 -> {
                        "${creator.name}, ${rumbleSearchResult.views} views"
                    }

                    else -> {
                        creator.name ?: ""
                    }
                }

                Row {
                    Text(text)

                    if (creator.isVerified) {
                        Icon(
                            painter = painterResource(R.drawable.ic_baseline_verified_24),
                            tint = Color.Cyan,
                            contentDescription = stringResource(id = R.string.mainActivity_verified_content_description)
                        )
                    }
                }
            }
        },

        leadingContent = {
            AsyncImage(
                rumbleSearchResult.thumbnailSrc,
                contentDescription = null,
                modifier = Modifier.size(100.dp, 100.dp)
            )
        },

        modifier = Modifier.clickable {
            onClick.invoke()
        }
    )
    Divider()
}

Основные составные:

      LazyColumn {
    items(viewModel.searchResults) {
        RumbleSearchResult(rumbleSearchResult = it) {
            openDialog = true
        }
    }
}

Вы должны следовать шаблону государственного хостинга от Android Domcumentaiton

Ключевой термин: подъем состояния - это шаблон перемещения состояния вверх по дереву, чтобы сделать компонент без состояния.

Применительно к составным элементам это часто означает введение в составной объект двух параметров:

value: T: текущее значение для отображения. onValueChange: (T) -> Unit: событие, которое запрашивает изменение значения, где T - это предлагаемое новое значение.

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

Другие вопросы по тегам