LazyColumn с изображением из источника растрового изображения мигает / мигает

Я новичок в Jetpack Compose. В настоящее время я разрабатываю приложение для чата. Прошу пользователя выбрать изображение из галереи или сделать снимок с камеры. Затем я сохраняю файл Uri в базе данных и затем слушаю список всех сообщений. Когда этот список обновляется, это изображение перекомпоновывается и мигает.

Список сообщений в модели просмотра:

      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
                )
                ...
            }
        }
    }

Мой SentImageBlock:

      @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 ответ

Решение

LazyColumnповторно использует представления для элементов, используя аргумент, и по умолчанию он равен индексу элемента. Вы можете предоставить правильный 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
            )
                ...
        }
    }
}
Другие вопросы по тегам