Отсутствует рекомпозиция при изменении состояния пользовательского интерфейса.Android

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Отсутствует рекомпозиция при изменении состояния пользовательского интерфейса.

Сообщение Anonymous »

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

Код: Выделить всё

data class RecordsAppUiState(
val records : Flow,
val searchValue : String,
val category: Category = Category.ALL,
)

class RecordAppViewModel(var context: Context) : ViewModel() {
private var repository: LocalRecordsRepository =
LocalKitsRepository(RecordAppDatabase.getDatabase(context).recordDao())
private var recordsInDatabase = repository.getAllRecordsStream()
private var currentCategory = Category.ALL
private val _uiState: MutableStateFlow =
MutableStateFlow(
RecordsAppUiState(
records = recordsInDatabase,
searchValue = "",
)
)
val uiState = _uiState.asStateFlow()

fun onSearchValueChanged(newSearchValue: String) {
_uiState.value = _uiState.value.copy(
searchValue = newSearchValue,
records = recordsInDatabase.map { records ->
records.filter { record ->
(record.name.contains(newSearchValue, ignoreCase = true))
}
},
category = currentCategory,
)
}

// Adds the record to the wishlist
fun addRecordToUserWishlist(record: Record) {
record.IsInWishlist = !record.IsInWishlist
viewModelScope.launch(Dispatchers.IO) {
repository.updateRecord(record)
}
_uiState.value = _uiState.value.copy(
records =
recordsInDatabase.map { listRecords ->
listRecords.map { oldRecord ->
if (oldRecord.uid == record.uid) oldRecord.copy(
IsInWishlist = record.IsInWishlist,
) else oldRecord
}
},
)
}
}
onSearchValueChanged обновляет мой список напрямую, но мне приходится принудительно рекомпоновать (прокручивать вниз, а затем вверх), чтобы увидеть изменения в кнопках с помощью addRecordToUserWishlist.
Вот составной элемент, где я нажимаю значок:

Код: Выделить всё

@Composable
fun RecordAppCard(
record: Record,
addWishlistClicked: (Record) -> Unit,
) {
Card {
Text(
text = record.name,
)

Row {
IconButton(onClick = {
addWishlistClicked(record) // Calls addRecordToUserWishlist from viewModel above
}) {
Icon(
imageVector = if (record.IsInWishlist) Icons.Default.Favorite else Icons.Default.FavoriteBorder,
contentDescription = "wishlist",
)
}
}
}
}
А вот главный экран со списком карт RecordAppCard:

Код: Выделить всё

@Composable
fun RecordAppsMainScreen(
modifier: Modifier = Modifier,
viewModel: RecordAppViewModel = viewModel(),
) {
val uiState = viewModel.uiState.collectAsStateWithLifecycle()
val flowRecords = uiState.value.records
val listRecords = flowRecords.collectAsState(initial = emptyList()).value

LazyColumn(
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
item {
RecordAppSearchBar(
searchValue = uiState.value.searchValue,
onSearchChange = { viewModel.onSearchValueChanged(it) },
)
}
items(listRecords) { record ->
RecordAppCard(
record = record,
addWishlistClicked = { viewModel.addRecordToUserWishlist(record) },
)
}
}
}
Я также попробовал другой способ: я добавил переменную в составную функцию RecordAppCard:

Код: Выделить всё

var inWishlist by remember { mutableStateOf(kit.IsInWishlist) }
Это «работает», так как IconButton обновляется напрямую, но если я прокручиваю вниз, у меня начинаются проблемы, например, значки заполняются тогда, когда этого не должно быть, поэтому я не уверен, что это правильный путь.>

Подробнее здесь: https://stackoverflow.com/questions/797 ... e-ui-state
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»