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

#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. Это работает. Очень вам благодарен :молитесь: