重组未按我的预期工作,图像未显示

问题描述 投票:0回答:1

我制作可组合的EventCard项目,从API获取图像(我从位图中的API获取,因为图像URL受令牌保护)。但有时卡片会显示所有默认图像,有时所有卡片都会显示一张卡片的图像。 像这样: card list not showing image 然后当我向上滚动时: card list showing image from one card 我的活动卡代码在这里:

@Composable
fun EventsScreen(navController: NavHostController, user: User?) {
    val viewModel: EventViewModel = hiltViewModel()
    val events by viewModel.events.collectAsState()

    val category by remember { mutableStateOf(EventCategory.EDUCATIVE) }
    var search by remember { mutableStateOf("") }

    BaseComponent(navController, user, "Listado Eventos", false) {
        Column(
            modifier = Modifier.padding(12.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceBetween,
                verticalAlignment = Alignment.CenterVertically
            ) {
                OutlinedTextField(
                    modifier = Modifier.fillMaxWidth(),
                    value = search,
                    onValueChange = {
                        search = it
                        viewModel.viewModelScope.launch {
                            viewModel.getEvents(search)
                        }
                    },
                    label = {
                        Text("Buscar")
                    },
                    placeholder = {
                        Text("Curso de ...")
                    }
                )
            }
            Row {
                /* TODO busqueda por categoria */
            }
            Row {
                LazyColumn(
                    modifier = Modifier,
                    verticalArrangement = Arrangement.spacedBy(8.dp),
                    userScrollEnabled = true,
                ) {
                    items(events.content) { event ->
                        key (event.id) {
                            EventCard(navController, event)
                        }
                    }
                }
            }
        }
    }
}

这是卡代码:

package frgp.utn.edu.ar.quepasa.presentation.ui.components.events.card

import android.annotation.SuppressLint
import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import coil3.compose.AsyncImage
import frgp.utn.edu.ar.quepasa.R
import frgp.utn.edu.ar.quepasa.data.model.Event
import frgp.utn.edu.ar.quepasa.presentation.ui.components.events.card.components.CardButtonsBar
import frgp.utn.edu.ar.quepasa.presentation.ui.components.text.ReadMoreText
import frgp.utn.edu.ar.quepasa.presentation.viewmodel.media.EventPictureViewModel
import frgp.utn.edu.ar.quepasa.presentation.viewmodel.media.PictureViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

@Composable
fun EventCard(navController: NavHostController, event: Event) {
    val context = LocalContext.current
    val eventPictureViewModel: EventPictureViewModel = hiltViewModel()
    val pictureViewModel: PictureViewModel = hiltViewModel()
    val bitmap by pictureViewModel.bitmap.collectAsState()
    val pictures by eventPictureViewModel.pictures.collectAsState()
    LaunchedEffect(Unit) {
        eventPictureViewModel.getPicturesByEvent(event.id!!)
        pictures.content.firstOrNull()
            ?.let { pictureViewModel.setPictureBitmap(it.id) }
    }
    ElevatedCard(
        onClick = {
            Toast.makeText(
                context,
                "Card Clicked",
                Toast.LENGTH_SHORT
            ).show()
            navController.navigate("eventDetailedScreen/${event.id}")
        },
        modifier = Modifier
            .fillMaxWidth()
            .height(IntrinsicSize.Max),
        shape = RoundedCornerShape(10.dp),
        elevation = CardDefaults.cardElevation(
            defaultElevation = 6.dp
        ),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.primaryContainer
        )
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(4.dp),
            horizontalArrangement = Arrangement.spacedBy(8.dp)
        ) {
            Column {
                if (bitmap != null && pictures.content.firstOrNull() != null) {
                    AsyncImage(
                        model = bitmap,
                        modifier = Modifier
                            .size(100.dp)
                            .border(
                                1.dp,
                                MaterialTheme.colorScheme.secondary,
                                RoundedCornerShape(10.dp)
                            ).clip(shape = MaterialTheme.shapes.medium),
                        contentDescription = "Event Image",
                        contentScale = ContentScale.Crop,
                    )
                } else {
                    Image(
                        painter = painterResource(R.drawable.baseline_broken_image_24),
                                modifier = Modifier
                                .size(100.dp)
                            .border(
                                1.dp,
                                MaterialTheme.colorScheme.secondary,
                                RoundedCornerShape(10.dp)
                            ).clip(shape = MaterialTheme.shapes.medium),
                        contentDescription = "No Image",
                        contentScale = ContentScale.Crop,
                    )
                }
            }
            Column {
                event.title?.let {
                    Text(
                        text = it,
                        modifier = Modifier.padding(6.dp),
                        style = MaterialTheme.typography.titleLarge,
                        overflow = TextOverflow.Ellipsis,
                        maxLines = 1
                    )
                }
                HorizontalDivider(
                    thickness = 2.dp,
                    color = MaterialTheme.colorScheme.secondary
                )
                event.description?.let {
                    ReadMoreText(
                        it,
                        Modifier.padding(16.dp), MaterialTheme.typography.bodyLarge,
                        1,
                        10
                    )
                }
            }
        }
        event.votes?.let { event.id?.let { id -> CardButtonsBar(id, it) } }
    }
}

图片视图模型代码:

@HiltViewModel
class PictureViewModel @Inject constructor(
    private val repository: PictureRepository
) : ViewModel() {
    private val _bitmap = MutableStateFlow<Bitmap?>(null)
    val bitmap = _bitmap.asStateFlow()
    fun setBitmap(bitmap: Bitmap) {
        _bitmap.value = bitmap
    }

    private val _pictures = MutableStateFlow<List<Bitmap?>>(emptyList())
    val pictures = _pictures.asStateFlow()

    fun setPictureBitmap(pictureId: UUID) {
        repository.viewPicture(pictureId, onComplete = {
            _bitmap.value = it
        })
    }

    fun setPicturesBitmap(pictureIds: List<UUID>) {
        val bitmaps = mutableListOf<Bitmap?>()
        pictureIds.forEach { pictureId ->
            repository.viewPicture(pictureId, onComplete = {
                bitmaps.add(it)
                _pictures.value = bitmaps
            })
        }
    }
}

EventViewModel 从 API 获取事件列表 我不明白我做错了什么,提前谢谢!

android-jetpack-compose android-viewmodel android-jetpack-compose-material3 card
1个回答
0
投票

每个

EventCard
使用相同的
ViewModel
,因此每张卡片都使用相同的
PictureViewModel.bitmap
。您应该将
Bitmap
保存在
Event
模型中,这样每个事件都会有其图像。

© www.soinside.com 2019 - 2024. All rights reserved.