Anonymous
LazyColumn вызывает задержку из-за вычислений для каждого элемента. Как его оптимизировать?
Сообщение
Anonymous » 26 дек 2024, 09:18
У меня наблюдается значительная задержка при отображении LazyColumn в приложении Jetpack Compose. Каждый элемент включает в себя некоторые вычисления (например, вычисление оставшегося времени), и я загружаю изображения асинхронно с помощью Coil. Это вызывает проблемы с производительностью, особенно во время прокрутки.
Вот соответствующий код:
У меня есть класс данных FeedViewState и FeedViewModel, который извлекает разбивку на страницы. список объектов опроса с сервера. LazyColumn отображает этот список, и когда пользователь прокручивает его до конца, я получаю больше данных (нумерация страниц).
Код: Выделить всё
@Composable
fun FeedComp(
mainViewModel: MainViewModel,
mainHomeVM: MainHomeViewModel,
showBottomSheet: MutableState,
navControllerMain: NavController,
) {
// Initial data fetch
LaunchedEffect(Unit) {
feedVM.GetFeedFunctionality(mainViewModel)
}
val listState = rememberLazyListState()
Scaffold(
modifier = Modifier.blur(if (showBottomSheet.value) 15.dp else 0.dp),
topBar = {
MainHomeTopBarComp(mainViewModel = mainViewModel, showBottomSheet)
},
) { paddingValues ->
Box(Modifier.fillMaxSize()) {
LazyColumn(
state = listState,
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.background(Color.White),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
item { Spacer(modifier = Modifier.height(8.dp)) }
items(state.FeedList) { poll ->
PollItem(
poll = poll,
mainViewModel = mainViewModel,
navControllerMain = navControllerMain,
pollReportId = pollReportId,
showManagementDialog = showManagementDialog,
managementOwner = managementOwner,
feedVM = feedVM
) // Each PollItem involves calculations and Coil image loading
}
}
}
}
// Pagination - fetch more data when user scrolls close to the end
LaunchedEffect(listState.firstVisibleItemIndex) {
val visibleItemCount = listState.layoutInfo.visibleItemsInfo.size
val totalItemCount = listState.layoutInfo.totalItemsCount
val lastVisibleItemIndex = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
if (lastVisibleItemIndex >= totalItemCount - 3 && !state.loading) {
feedVM.GetFeedFunctionality(mainViewModel)
}
}
}
ViewModel и данные:
Код: Выделить всё
data class FeedViewState(
val loading: Boolean = false,
var FeedList: List
= emptyList(),
)
@HiltViewModel
class FeedViewModel @Inject constructor(
private val feedRepository: FeedRepository,
) : ViewModel() {
private val _state = MutableStateFlow(FeedViewState())
val state = _state.asStateFlow()
private var currentPage by mutableStateOf(1)
fun GetFeedFunctionality(mainViewModel: MainViewModel) {
if (state.value.loading) return
val pageSize = 10
val token = "Bearer ${mainViewModel.GetToken()}"
viewModelScope.launch {
_state.update { it.copy(loading = true) }
feedRepository.getFeed(token = token, pageSize = pageSize, pageNumber = currentPage)
.onRight { response ->
if (response.isSuccessful) {
response.body()?.data?.polls?.let { polls ->
_state.update {
it.copy(
FeedList = it.FeedList + polls
)
}
currentPage++
}
}
}
.onLeft { error ->
Log.e("FeedViewModel", "Network error: ${error.error.message}")
}
_state.update { it.copy(loading = false) }
}
}
}
Компонуемый PollItem:
Каждый PollItem включает в себя некоторые вычисления и загрузку изображений с использованием Coil.
каждый опрос (объект) представляет собой класс данных, который я получил от API
Код: Выделить всё
data class Poll(
val commentCloesed: Boolean,
val createdAt: String,
val endedAt: String,
val id: String,
var isPollUp: Boolean,
var likes: Int,
val maximumParticipate: Int,
var numberofcommnets: Int,
var numberofshare: Int,
val numberofviews: Int,
val options: List,
val owner: Owner?,
val isOwner:Boolean,
var participate: Int,
val pollUrl: String,
val polltype: Int,
val question: String,
val isAlphaUser:Boolean,
val isAlpha:Boolean,
val isSensitive:Boolean,
var status: Int,
val tags: List,
val topics: List,
var user: List,
var userCommentedPoll: Boolean,
var userLike: Boolean,
var userReShare: Boolean,
val userViewedPoll: Boolean,
var userVotedOnPoll: Boolean,
val votingtype: Int,
var deleted :Boolean = false
)
Код: Выделить всё
@Composable
fun PollItem(
poll: Poll,
mainViewModel: MainViewModel,
navControllerMain: NavController,
pollReportId: MutableState,
showManagementDialog: MutableState,
managementOwner: MutableState,
feedVM: FeedViewModel
) {
val screenHeight = LocalConfiguration.current.screenHeightDp.dp
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
if (!poll.deleted) {
Column(
Modifier
.fillMaxWidth()
.padding(end = 16.dp, start = 16.dp, bottom = 8.dp)
.clip(RoundedCornerShape(4.dp))
.background(backgroundpollcard)
.pointerInput(Unit) {
detectTapGestures(
onTap = {
mainViewModel.rememberedPoll.value = poll
navControllerMain.navigate("pollPage/${poll.id}")
},
onLongPress = {
pollReportId.value = poll.id
managementOwner.value = poll.isOwner
showManagementDialog.value = true
}
)
}
.padding(16.dp)
) {
//polled up by who
if (poll.isPollUp) {
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Box(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(4.dp))
.border(1.dp, textSecondary, RoundedCornerShape(4.dp))
.background(backgroundTabs)
.padding(8.dp),
contentAlignment = Alignment.Center
) {
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
painter = painterResource(id = R.drawable.unpollup),
contentDescription = "pollup icon",
tint = textSecondary,
modifier = Modifier
.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
fontFamily = sfPro,
text = "PollUpped by ",
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 14.sp,
fontWeight = FontWeight(400),
color = textSecondary
)
val currentUserId =
mainViewModel.singedInProfileResponse.value?.data?.id
val userName =
poll.user.find { it.userId == currentUserId }
?.let { "You" }
?: poll.user.firstOrNull()?.userName
?: poll.user[0].userName
Text(
modifier = Modifier
.sizeIn(maxWidth = 100.dp)
// .background(Color.LightGray)
,
overflow = TextOverflow.Ellipsis,
fontFamily = sfPro,
text = "$userName",
maxLines = 1,
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 14.sp,
fontWeight = FontWeight(600),
color = textSecondary
)
if (poll.user.size > 1) {
Text(
fontFamily = sfPro,
text = " and ",
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 14.sp,
fontWeight = FontWeight(400),
color = textSecondary
)
Text(
overflow = TextOverflow.Ellipsis,
fontFamily = sfPro,
text = "${poll.user.size - 1}",
maxLines = 1,
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 14.sp,
fontWeight = FontWeight(600),
color = textSecondary
)
Text(
fontFamily = sfPro,
text = "${if (poll.user.size - 1 > 1) "others" else "other"}",
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 14.sp,
fontWeight = FontWeight(400),
color = textSecondary
)
}
}
}
}
Spacer(modifier = Modifier.height(24.dp))
}
//profile & progress
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
modifier = Modifier
.size(40.dp)
.clip(RoundedCornerShape(100))
.background(Color.LightGray)
) {
if (poll.owner != null) {
if (poll.owner.pictureUrl != null && poll.owner.pictureUrl != "") {
AsyncImage(
modifier = Modifier.fillMaxSize(),
model = poll.owner?.pictureUrl,
contentDescription = "poll owner profile image",
contentScale = ContentScale.Crop
)
} else {
Image(
painter = painterResource(id = R.drawable.defaultprof),
modifier = Modifier.fillMaxSize(),
contentDescription = "poll owner profile image",
contentScale = ContentScale.Crop
)
}
} else {
Image(
painter = painterResource(id = R.drawable.anonymous_emblem),
modifier = Modifier.fillMaxSize(),
contentDescription = "poll owner profile image",
contentScale = ContentScale.Crop
)
}
}
Spacer(modifier = Modifier.width(8.dp))
if (poll.owner != null) {
Column(Modifier.offset(y = -2.dp)) {
Row(verticalAlignment = Alignment.CenterVertically) {
poll.owner?.firstName?.let {
Text(
fontFamily = sfPro,
text = it,
fontSize = 16.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 19.sp,
fontWeight = FontWeight(500),
color = textSecondary
)
}
if (poll.isAlphaUser) {
Spacer(modifier = Modifier.width(8.dp))
Image(
painter = painterResource(id = R.drawable.alpha),
contentDescription = "alpha sign",
modifier = Modifier
.size(17.dp)
)
}
}
Spacer(modifier = Modifier.height(8.dp))
Text(
fontFamily = sfPro,
text = "@" + poll.owner?.userName,
fontSize = 10.sp,
// letterSpacing = (-0.41).sp,
lineHeight = 11.sp,
fontWeight = FontWeight(500),
color = textThirt
)
}
} else {
Text(
fontFamily = sfPro,
text = "Anonymous Poll",
fontSize = 16.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 19.sp,
fontWeight = FontWeight(500),
color = textSecondary
)
//todo:inja YOU biyad , fix condition
if (poll.isOwner == true) {
Spacer(modifier = Modifier.width(8.dp))
Text(
modifier = Modifier
.border(
0.5.dp,
color = textSecondary,
RoundedCornerShape(4.dp)
)
.padding(
start = 6.dp,
end = 6.dp
),
fontFamily = sfPro,
text = "You",
fontSize = 8.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 19.sp,
fontWeight = FontWeight(500),
color = textSecondary
)
}
}
}
Box(contentAlignment = Alignment.Center) {
if (poll.status == 1) {
CircularProgressIndicator(
modifier = Modifier.size(40.dp),
strokeWidth = 2.dp,
color = feedVM.timeRemaining(poll.endedAt).second,
trackColor = strokesVoteTime,
strokeCap = StrokeCap.Round,
progress = {
feedVM.calculatePercentage(
startDate = poll.createdAt,
endDate = poll.endedAt
)
}
)
Box {
Text(
fontFamily = sfPro,
text = "${feedVM.timeRemaining(poll.endedAt).first}",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(500),
color = if (poll.status == 0) textthird else feedVM.timeRemaining(
poll.endedAt
).second
)
}
} else {
CircularProgressIndicator(
modifier = Modifier.size(40.dp),
strokeWidth = 2.dp,
color = textthird,
trackColor = strokesVoteTime,
strokeCap = StrokeCap.Round,
progress = {
1f
}
)
Box {
Text(
fontFamily = sfPro,
text = "Ended",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(500),
color = textthird
)
}
}
}
}
Spacer(modifier = Modifier.height(16.dp))
//question
Box(modifier = Modifier.fillMaxWidth()) {
HashtagText(
text = poll.question,
onHashtagClick = { hashtag ->
navControllerMain.navigate("pollPage/${poll.id}")
println("Hashtag clicked: $hashtag")
},
onTextClick = {
navControllerMain.navigate("pollPage/${poll.id}")
println("Non-hashtag text clicked!")
}
)
}
//first option
if (poll.options.isNotEmpty()) {
Spacer(modifier = Modifier.height(16.dp))
if (poll.options[0].type == 0) {//means its text poll
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
CustomRadioButton(
isSelected = mutableStateOf(poll.options[0].userChoose),
onClick = {},
borderColor = textthird,
size = 16.dp,
dotColor = textthird,
isEnabled = false
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Text(
fontFamily = sfPro,
text = poll.options[0].title,
fontSize = 14.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 17.sp,
fontWeight = FontWeight(500),
color = textSecondary
)
Spacer(modifier = Modifier.height(4.dp))
Box(
modifier = Modifier
.fillMaxWidth()
.height(2.dp)
.background(if (poll.options[0].userChoose) textthird else strokesVoteTime)
)
}
}
} else {//means its image poll
// Text(text = "${(screenHeight*9/ 40)}")
Box(
modifier = Modifier
.fillMaxWidth()
.height(screenHeight * 9 / 40)
.clip(RoundedCornerShape(4.dp))
.background(Color.LightGray)
) {
AsyncImage(
model = poll.options[0].data,
contentDescription = null,
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
}
}
//more option(s)
Spacer(modifier = Modifier.height(8.dp))
Row(Modifier.fillMaxWidth()) {
Text(
fontFamily = sfPro,
text = "${poll.options.size - 1} more ${if (poll.options.size - 1 == 1) "option" else "options"}",
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 15.sp,
fontWeight = FontWeight(400),
color = textthird
)
}
//like comment
Spacer(modifier = Modifier.height(16.dp))
Row(
Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
//alpha
if (poll.isAlpha) {
Text(
fontFamily = sfPro,
text = "Alpha",
fontSize = 12.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 15.sp,
fontWeight = FontWeight(600),
color = textImportant
)
}
//comment
if (!poll.commentCloesed) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
modifier = Modifier.size(17.dp),
painter = if (poll.userCommentedPoll)
painterResource(id = R.drawable.comment)
else
painterResource(id = R.drawable.uncomment),
tint = if (poll.status == 1) if (poll.userCommentedPoll) iconsFunctionalityComment else iconsFunctionalityDefault else textthird,
contentDescription = "icon"
)
Spacer(modifier = Modifier.width(4.dp))
Text(
fontFamily = sfPro,
text = "${poll.numberofcommnets}",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(400),
color = iconsFunctionalityDefault
)
}
}
//like
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
modifier = Modifier.size(17.dp),
painter = if (poll.userLike)
painterResource(id = R.drawable.like)
else
painterResource(id = R.drawable.unlike),
tint = if (poll.status == 1) if (poll.userLike) iconsFunctionalityLike else iconsFunctionalityDefault else textthird,
contentDescription = "icon"
)
Spacer(modifier = Modifier.width(4.dp))
Text(
fontFamily = sfPro,
text = "${poll.likes}",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(400),
color = iconsFunctionalityDefault
)
}
//pollup
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
modifier = Modifier.size(17.dp),
painter = if (poll.userReShare)
painterResource(id = R.drawable.pollup)
else
painterResource(id = R.drawable.unpollup),
tint = if (poll.status == 1) if (poll.userReShare) iconsFunctionalityPollup else iconsFunctionalityDefault else textthird,
contentDescription = "icon"
)
Spacer(modifier = Modifier.width(4.dp))
Text(
fontFamily = sfPro,
text = "${poll.numberofshare}",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(400),
color = iconsFunctionalityDefault
)
}
//voters
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
modifier = Modifier.size(17.dp),
painter = if (poll.userVotedOnPoll)
painterResource(id = R.drawable.vote)
else
painterResource(id = R.drawable.unvote),
tint = if (poll.status == 1) if (poll.userVotedOnPoll) iconsFunctionalityVoter else iconsFunctionalityDefault else textthird,
contentDescription = "icon"
)
Spacer(modifier = Modifier.width(4.dp))
Text(
fontFamily = sfPro,
text = "${poll.participate}",
fontSize = 10.sp,
//letterSpacing = (-0.41).sp,
lineHeight = 12.sp,
fontWeight = FontWeight(400),
color = iconsFunctionalityDefault
)
}
}
}
}
}
Моя проблема:
LazyColumn вызывает задержку, особенно во время прокрутки.
Каждый PollItem требует вычислений, а изображения загружаются асинхронно с помощью Coil.>
Подробнее здесь:
https://stackoverflow.com/questions/790 ... ptimize-it
1735193893
Anonymous
У меня наблюдается значительная задержка при отображении LazyColumn в приложении Jetpack Compose. Каждый элемент включает в себя некоторые вычисления (например, вычисление оставшегося времени), и я загружаю изображения асинхронно с помощью Coil. Это вызывает проблемы с производительностью, особенно во время прокрутки. Вот соответствующий код: У меня есть класс данных FeedViewState и FeedViewModel, который извлекает разбивку на страницы. список объектов опроса с сервера. LazyColumn отображает этот список, и когда пользователь прокручивает его до конца, я получаю больше данных (нумерация страниц). [code]@Composable fun FeedComp( mainViewModel: MainViewModel, mainHomeVM: MainHomeViewModel, showBottomSheet: MutableState, navControllerMain: NavController, ) { // Initial data fetch LaunchedEffect(Unit) { feedVM.GetFeedFunctionality(mainViewModel) } val listState = rememberLazyListState() Scaffold( modifier = Modifier.blur(if (showBottomSheet.value) 15.dp else 0.dp), topBar = { MainHomeTopBarComp(mainViewModel = mainViewModel, showBottomSheet) }, ) { paddingValues -> Box(Modifier.fillMaxSize()) { LazyColumn( state = listState, modifier = Modifier .fillMaxSize() .padding(paddingValues) .background(Color.White), verticalArrangement = Arrangement.spacedBy(8.dp) ) { item { Spacer(modifier = Modifier.height(8.dp)) } items(state.FeedList) { poll -> PollItem( poll = poll, mainViewModel = mainViewModel, navControllerMain = navControllerMain, pollReportId = pollReportId, showManagementDialog = showManagementDialog, managementOwner = managementOwner, feedVM = feedVM ) // Each PollItem involves calculations and Coil image loading } } } } // Pagination - fetch more data when user scrolls close to the end LaunchedEffect(listState.firstVisibleItemIndex) { val visibleItemCount = listState.layoutInfo.visibleItemsInfo.size val totalItemCount = listState.layoutInfo.totalItemsCount val lastVisibleItemIndex = listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0 if (lastVisibleItemIndex >= totalItemCount - 3 && !state.loading) { feedVM.GetFeedFunctionality(mainViewModel) } } } [/code] ViewModel и данные: [code]data class FeedViewState( val loading: Boolean = false, var FeedList: List = emptyList(), ) @HiltViewModel class FeedViewModel @Inject constructor( private val feedRepository: FeedRepository, ) : ViewModel() { private val _state = MutableStateFlow(FeedViewState()) val state = _state.asStateFlow() private var currentPage by mutableStateOf(1) fun GetFeedFunctionality(mainViewModel: MainViewModel) { if (state.value.loading) return val pageSize = 10 val token = "Bearer ${mainViewModel.GetToken()}" viewModelScope.launch { _state.update { it.copy(loading = true) } feedRepository.getFeed(token = token, pageSize = pageSize, pageNumber = currentPage) .onRight { response -> if (response.isSuccessful) { response.body()?.data?.polls?.let { polls -> _state.update { it.copy( FeedList = it.FeedList + polls ) } currentPage++ } } } .onLeft { error -> Log.e("FeedViewModel", "Network error: ${error.error.message}") } _state.update { it.copy(loading = false) } } } } [/code] Компонуемый PollItem: Каждый PollItem включает в себя некоторые вычисления и загрузку изображений с использованием Coil. каждый опрос (объект) представляет собой класс данных, который я получил от API [code]data class Poll( val commentCloesed: Boolean, val createdAt: String, val endedAt: String, val id: String, var isPollUp: Boolean, var likes: Int, val maximumParticipate: Int, var numberofcommnets: Int, var numberofshare: Int, val numberofviews: Int, val options: List, val owner: Owner?, val isOwner:Boolean, var participate: Int, val pollUrl: String, val polltype: Int, val question: String, val isAlphaUser:Boolean, val isAlpha:Boolean, val isSensitive:Boolean, var status: Int, val tags: List, val topics: List, var user: List, var userCommentedPoll: Boolean, var userLike: Boolean, var userReShare: Boolean, val userViewedPoll: Boolean, var userVotedOnPoll: Boolean, val votingtype: Int, var deleted :Boolean = false ) [/code] [code]@Composable fun PollItem( poll: Poll, mainViewModel: MainViewModel, navControllerMain: NavController, pollReportId: MutableState, showManagementDialog: MutableState, managementOwner: MutableState, feedVM: FeedViewModel ) { val screenHeight = LocalConfiguration.current.screenHeightDp.dp val screenWidth = LocalConfiguration.current.screenWidthDp.dp if (!poll.deleted) { Column( Modifier .fillMaxWidth() .padding(end = 16.dp, start = 16.dp, bottom = 8.dp) .clip(RoundedCornerShape(4.dp)) .background(backgroundpollcard) .pointerInput(Unit) { detectTapGestures( onTap = { mainViewModel.rememberedPoll.value = poll navControllerMain.navigate("pollPage/${poll.id}") }, onLongPress = { pollReportId.value = poll.id managementOwner.value = poll.isOwner showManagementDialog.value = true } ) } .padding(16.dp) ) { //polled up by who if (poll.isPollUp) { Row( Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Box( modifier = Modifier .fillMaxWidth() .clip(RoundedCornerShape(4.dp)) .border(1.dp, textSecondary, RoundedCornerShape(4.dp)) .background(backgroundTabs) .padding(8.dp), contentAlignment = Alignment.Center ) { Row( Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Icon( painter = painterResource(id = R.drawable.unpollup), contentDescription = "pollup icon", tint = textSecondary, modifier = Modifier .size(20.dp) ) Spacer(modifier = Modifier.width(8.dp)) Text( fontFamily = sfPro, text = "PollUpped by ", fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 14.sp, fontWeight = FontWeight(400), color = textSecondary ) val currentUserId = mainViewModel.singedInProfileResponse.value?.data?.id val userName = poll.user.find { it.userId == currentUserId } ?.let { "You" } ?: poll.user.firstOrNull()?.userName ?: poll.user[0].userName Text( modifier = Modifier .sizeIn(maxWidth = 100.dp) // .background(Color.LightGray) , overflow = TextOverflow.Ellipsis, fontFamily = sfPro, text = "$userName", maxLines = 1, fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 14.sp, fontWeight = FontWeight(600), color = textSecondary ) if (poll.user.size > 1) { Text( fontFamily = sfPro, text = " and ", fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 14.sp, fontWeight = FontWeight(400), color = textSecondary ) Text( overflow = TextOverflow.Ellipsis, fontFamily = sfPro, text = "${poll.user.size - 1}", maxLines = 1, fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 14.sp, fontWeight = FontWeight(600), color = textSecondary ) Text( fontFamily = sfPro, text = "${if (poll.user.size - 1 > 1) "others" else "other"}", fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 14.sp, fontWeight = FontWeight(400), color = textSecondary ) } } } } Spacer(modifier = Modifier.height(24.dp)) } //profile & progress Row( Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { Row(verticalAlignment = Alignment.CenterVertically) { Box( modifier = Modifier .size(40.dp) .clip(RoundedCornerShape(100)) .background(Color.LightGray) ) { if (poll.owner != null) { if (poll.owner.pictureUrl != null && poll.owner.pictureUrl != "") { AsyncImage( modifier = Modifier.fillMaxSize(), model = poll.owner?.pictureUrl, contentDescription = "poll owner profile image", contentScale = ContentScale.Crop ) } else { Image( painter = painterResource(id = R.drawable.defaultprof), modifier = Modifier.fillMaxSize(), contentDescription = "poll owner profile image", contentScale = ContentScale.Crop ) } } else { Image( painter = painterResource(id = R.drawable.anonymous_emblem), modifier = Modifier.fillMaxSize(), contentDescription = "poll owner profile image", contentScale = ContentScale.Crop ) } } Spacer(modifier = Modifier.width(8.dp)) if (poll.owner != null) { Column(Modifier.offset(y = -2.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { poll.owner?.firstName?.let { Text( fontFamily = sfPro, text = it, fontSize = 16.sp, //letterSpacing = (-0.41).sp, lineHeight = 19.sp, fontWeight = FontWeight(500), color = textSecondary ) } if (poll.isAlphaUser) { Spacer(modifier = Modifier.width(8.dp)) Image( painter = painterResource(id = R.drawable.alpha), contentDescription = "alpha sign", modifier = Modifier .size(17.dp) ) } } Spacer(modifier = Modifier.height(8.dp)) Text( fontFamily = sfPro, text = "@" + poll.owner?.userName, fontSize = 10.sp, // letterSpacing = (-0.41).sp, lineHeight = 11.sp, fontWeight = FontWeight(500), color = textThirt ) } } else { Text( fontFamily = sfPro, text = "Anonymous Poll", fontSize = 16.sp, //letterSpacing = (-0.41).sp, lineHeight = 19.sp, fontWeight = FontWeight(500), color = textSecondary ) //todo:inja YOU biyad , fix condition if (poll.isOwner == true) { Spacer(modifier = Modifier.width(8.dp)) Text( modifier = Modifier .border( 0.5.dp, color = textSecondary, RoundedCornerShape(4.dp) ) .padding( start = 6.dp, end = 6.dp ), fontFamily = sfPro, text = "You", fontSize = 8.sp, //letterSpacing = (-0.41).sp, lineHeight = 19.sp, fontWeight = FontWeight(500), color = textSecondary ) } } } Box(contentAlignment = Alignment.Center) { if (poll.status == 1) { CircularProgressIndicator( modifier = Modifier.size(40.dp), strokeWidth = 2.dp, color = feedVM.timeRemaining(poll.endedAt).second, trackColor = strokesVoteTime, strokeCap = StrokeCap.Round, progress = { feedVM.calculatePercentage( startDate = poll.createdAt, endDate = poll.endedAt ) } ) Box { Text( fontFamily = sfPro, text = "${feedVM.timeRemaining(poll.endedAt).first}", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(500), color = if (poll.status == 0) textthird else feedVM.timeRemaining( poll.endedAt ).second ) } } else { CircularProgressIndicator( modifier = Modifier.size(40.dp), strokeWidth = 2.dp, color = textthird, trackColor = strokesVoteTime, strokeCap = StrokeCap.Round, progress = { 1f } ) Box { Text( fontFamily = sfPro, text = "Ended", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(500), color = textthird ) } } } } Spacer(modifier = Modifier.height(16.dp)) //question Box(modifier = Modifier.fillMaxWidth()) { HashtagText( text = poll.question, onHashtagClick = { hashtag -> navControllerMain.navigate("pollPage/${poll.id}") println("Hashtag clicked: $hashtag") }, onTextClick = { navControllerMain.navigate("pollPage/${poll.id}") println("Non-hashtag text clicked!") } ) } //first option if (poll.options.isNotEmpty()) { Spacer(modifier = Modifier.height(16.dp)) if (poll.options[0].type == 0) {//means its text poll Row( Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { CustomRadioButton( isSelected = mutableStateOf(poll.options[0].userChoose), onClick = {}, borderColor = textthird, size = 16.dp, dotColor = textthird, isEnabled = false ) Spacer(modifier = Modifier.width(8.dp)) Column { Text( fontFamily = sfPro, text = poll.options[0].title, fontSize = 14.sp, //letterSpacing = (-0.41).sp, lineHeight = 17.sp, fontWeight = FontWeight(500), color = textSecondary ) Spacer(modifier = Modifier.height(4.dp)) Box( modifier = Modifier .fillMaxWidth() .height(2.dp) .background(if (poll.options[0].userChoose) textthird else strokesVoteTime) ) } } } else {//means its image poll // Text(text = "${(screenHeight*9/ 40)}") Box( modifier = Modifier .fillMaxWidth() .height(screenHeight * 9 / 40) .clip(RoundedCornerShape(4.dp)) .background(Color.LightGray) ) { AsyncImage( model = poll.options[0].data, contentDescription = null, modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop ) } } } //more option(s) Spacer(modifier = Modifier.height(8.dp)) Row(Modifier.fillMaxWidth()) { Text( fontFamily = sfPro, text = "${poll.options.size - 1} more ${if (poll.options.size - 1 == 1) "option" else "options"}", fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 15.sp, fontWeight = FontWeight(400), color = textthird ) } //like comment Spacer(modifier = Modifier.height(16.dp)) Row( Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween ) { //alpha if (poll.isAlpha) { Text( fontFamily = sfPro, text = "Alpha", fontSize = 12.sp, //letterSpacing = (-0.41).sp, lineHeight = 15.sp, fontWeight = FontWeight(600), color = textImportant ) } //comment if (!poll.commentCloesed) { Row(verticalAlignment = Alignment.CenterVertically) { Icon( modifier = Modifier.size(17.dp), painter = if (poll.userCommentedPoll) painterResource(id = R.drawable.comment) else painterResource(id = R.drawable.uncomment), tint = if (poll.status == 1) if (poll.userCommentedPoll) iconsFunctionalityComment else iconsFunctionalityDefault else textthird, contentDescription = "icon" ) Spacer(modifier = Modifier.width(4.dp)) Text( fontFamily = sfPro, text = "${poll.numberofcommnets}", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(400), color = iconsFunctionalityDefault ) } } //like Row(verticalAlignment = Alignment.CenterVertically) { Icon( modifier = Modifier.size(17.dp), painter = if (poll.userLike) painterResource(id = R.drawable.like) else painterResource(id = R.drawable.unlike), tint = if (poll.status == 1) if (poll.userLike) iconsFunctionalityLike else iconsFunctionalityDefault else textthird, contentDescription = "icon" ) Spacer(modifier = Modifier.width(4.dp)) Text( fontFamily = sfPro, text = "${poll.likes}", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(400), color = iconsFunctionalityDefault ) } //pollup Row(verticalAlignment = Alignment.CenterVertically) { Icon( modifier = Modifier.size(17.dp), painter = if (poll.userReShare) painterResource(id = R.drawable.pollup) else painterResource(id = R.drawable.unpollup), tint = if (poll.status == 1) if (poll.userReShare) iconsFunctionalityPollup else iconsFunctionalityDefault else textthird, contentDescription = "icon" ) Spacer(modifier = Modifier.width(4.dp)) Text( fontFamily = sfPro, text = "${poll.numberofshare}", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(400), color = iconsFunctionalityDefault ) } //voters Row(verticalAlignment = Alignment.CenterVertically) { Icon( modifier = Modifier.size(17.dp), painter = if (poll.userVotedOnPoll) painterResource(id = R.drawable.vote) else painterResource(id = R.drawable.unvote), tint = if (poll.status == 1) if (poll.userVotedOnPoll) iconsFunctionalityVoter else iconsFunctionalityDefault else textthird, contentDescription = "icon" ) Spacer(modifier = Modifier.width(4.dp)) Text( fontFamily = sfPro, text = "${poll.participate}", fontSize = 10.sp, //letterSpacing = (-0.41).sp, lineHeight = 12.sp, fontWeight = FontWeight(400), color = iconsFunctionalityDefault ) } } } } } [/code] Моя проблема: LazyColumn вызывает задержку, особенно во время прокрутки. Каждый PollItem требует вычислений, а изображения загружаются асинхронно с помощью Coil.> Подробнее здесь: [url]https://stackoverflow.com/questions/79039785/lazycolumn-causing-lag-due-to-calculations-for-each-item-how-can-i-optimize-it[/url]