Состояние обновления вне составной функции. (Составить 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, вы можете узнать больше из официальной документации.