LazyColumn 与来自位图源的图像闪烁/闪烁

Posted

技术标签:

【中文标题】LazyColumn 与来自位图源的图像闪烁/闪烁【英文标题】:LazyColumn with Image from bitmap source blinking / flashing 【发布时间】:2021-11-25 18:03:06 【问题描述】:

我是 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
                )
                ...
            
        
    

我的已发送图像块:

@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())

我已经尝试了几件事,但图像总是闪烁。

【问题讨论】:

可以分享一些眨眼的视频吗? @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
            )
                ...
        
    

【讨论】:

它工作正常。非常感谢:祈祷:

以上是关于LazyColumn 与来自位图源的图像闪烁/闪烁的主要内容,如果未能解决你的问题,请参考以下文章

在基于位图的视频播放器上闪烁

SVG 图像在使用 css 变换移动时变得模糊和闪烁

Android:将数据添加到 ArrayAdapter 时可见的 ListView 图像闪烁

避免在调整大小时移动其控件的对话框上闪烁

在 MFC 中重绘时闪烁

Flutter ListView base64图像与Image.memory一起显示时闪烁