#android #kotlin #android-jetpack-compose #android-jetpack #lazycolumn
Вопрос:
Я новичок в создании реактивных ранцев. В настоящее время я разрабатываю приложение для чата. Я прошу пользователя выбрать изображение из галереи или сделать снимок с камеры. Затем я сохраняю Uri файла в базе данных, а затем прослушиваю список всех сообщений. Когда этот список обновляется, это изображение перестраивается и мигает.
Список сообщений в viewmodel:
private var _messages = MutableStateFlow<List<ChatUiMessage>>(mutableListOf())
val messages: StateFlow<List<ChatUiMessage>> = _messages
...
private fun observeMessages() {
viewModelScope.launch {
chatManager.observeMessagesFlow()
.flowOn(dispatcherIO)
.collect {
_messages.emit(it)
}
}
}
Главный экран чата:
...
val messages by viewModel.messages.collectAsState(listOf())
...
val listState = rememberLazyListState()
LazyColumn(
modifier = modifier.fillMaxWidth(),
reverseLayout = true,
state = listState
) {
itemsIndexed(items = messages) { index, message ->
when (message) {
...
is ChatUiMessage.Image -> SentImageBlock(
message = message
)
...
}
}
}
Мой блок сентиментальности:
@Composable
private fun SentImageBlock(message: ChatUiMessage.Image) {
val context = LocalContext.current
val bitmap: MutableState<Bitmap?> = rememberSaveable { mutableStateOf(null) }
bitmap.value ?: run {
LaunchedEffect(Unit) {
launch(Dispatchers.IO) {
bitmap.value = try {
when {
Build.VERSION.SDK_INT >= 28 -> {
val source = ImageDecoder.createSource(context.contentResolver, message.fileUriPath.toUri())
ImageDecoder.decodeBitmap(source)
}
else -> {
MediaStore.Images.Media.getBitmap(context.contentResolver, message.fileUriPath.toUri())
}
}
} catch (e: Exception) {
null
}
}
}
}
Box(
modifier = Modifier
.fillMaxWidth()
.padding(end = 16.dp, top = 16.dp, bottom = 16.dp)
.heightIn(max = 200.dp, min = 200.dp)
) {
bitmap.value?.let {
Image(
bitmap = it.asImageBitmap(),
contentDescription = null,
modifier = Modifier
.wrapContentSize()
.align(Alignment.CenterEnd)
)
}
}
StandardText(text = message.sendFileStatus.toString())
StandardText(text = message.fileType.toString())
}
Я перепробовал несколько вещей, и либо изображение всегда мигает.
Комментарии:
1. можете ли вы поделиться некоторыми видео мигания?
2. @NehaK Добавил пример
Ответ №1:
LazyColumn
повторно использует представления для элементов с использованием key
аргумента, и по умолчанию он равен индексу элемента. Вы можете предоставить правильное key
(что-то вроде сообщения id
) для правильного повторного использования представлений:
val messages = listOf(1,2,3)
LazyColumn(
modifier = modifier.fillMaxWidth(),
reverseLayout = true,
state = listState
) {
itemsIndexed(
items = messages,
key = { index, message -> message.id }
) { index, message ->
when (message) {
...
is ChatUiMessage.Image -> SentImageBlock(
message = message
)
...
}
}
}
Комментарии:
1. Это работает. Очень вам благодарен :молитесь: