Jetpack Compose LazyColumn Performance Issue

794 Views Asked by At

I'm writing example-screen with using lazyColumn. I encountered some performance issues on release build. Frame skipping happens when I fast-scroll the list. All models and composables are stable. My code is below;
Screen record link -> https://i.stack.imgur.com/bd2B5.jpg

viewModel:

@HiltViewModel
class ExampleViewModel @Inject constructor(
    private val repo: ExampleRepository,
) : ViewModel() {

    private val _viewState = MutableStateFlow(ItemsViewState())
    val viewState = _viewState.asStateFlow()

    init {
        fetch()
    }

    private fun fetch() = viewModelScope.launch {
        repo.getItems()
            .onStart { _viewState.value = _viewState.value.copy(state = PageState.Loading) }
            .onCompletion { _viewState.value = _viewState.value.copy(state = PageState.Content) }
            .collect { _viewState.value = _viewState.value.copy(items = it.toImmutableList()) }
    }
}

viewState and models:

data class ItemsViewState(
    val items: ImmutableList<Item> = persistentListOf(),
    val state: PageState = PageState.Loading,
)

data class Item(
    val id: Int,
    val imageUrl: String,
    val name: String,
    val rating: Double,
    val campaignText: String,
    val isChecked: Boolean = false,
)

data class ItemViewState(val item: Item) {

    fun isRatingVisible(): Boolean = item.rating > 7.0
}

sealed class PageState {

    object Content : PageState()

    object Loading : PageState()

    object Error : PageState()
}

and my composable functions:

@Composable
fun ExampleScreen(
    viewModel: ExampleViewModel = hiltViewModel(),
) {
    val viewState by viewModel.viewState.collectAsState()

    when (viewState.state) {
        PageState.Content -> {
            ExampleList(viewState = viewState)
        }
        PageState.Loading -> LoadingScreen()
        PageState.Error -> {}
    }
}

@Composable
private fun ExampleList(
    viewState: ItemsViewState,
) {
    LazyColumn(
        state = rememberLazyListState(),
        contentPadding = PaddingValues(16.dp),
        verticalArrangement = Arrangement.spacedBy(8.dp),
        modifier = Modifier.fillMaxSize()
    ) {
        items(viewState.items, key = { it.id }) { item ->
            ExampleListItem(item = item)
        }
    }
}

@Composable
private fun ExampleListItem(item: Item) {
    val viewState = ItemViewState(item)

    Card(
        shape = RoundedCornerShape(8.dp),
        backgroundColor = MaterialTheme.colors.background
    ) {
        Row(
            modifier = Modifier
                .padding(8.dp)
                .fillMaxWidth()
                .wrapContentHeight()
        ) {
            AsyncImage(
                model = item.imageUrl,
                contentDescription = viewState.item.name,
                contentScale = ContentScale.FillHeight,
                modifier = Modifier
                    .clip(RoundedCornerShape(10.dp))
                    .width(120.dp)
                    .height(120.dp),
            )
            Spacer(modifier = Modifier.width(8.dp))
            Column(verticalArrangement = Arrangement.SpaceBetween) {
                Row(horizontalArrangement = Arrangement.SpaceEvenly) {
                    Text(
                        text = viewState.item.name,
                        overflow = TextOverflow.Ellipsis,
                        maxLines = 1,
                        modifier = Modifier.weight(1f),
                    )
                    Icon(imageVector = Icons.Default.List, contentDescription = null)
                }
                Spacer(modifier = Modifier.height(2.dp))
                Row {
                    if (viewState.isRatingVisible()) {
                        Spacer(modifier = Modifier.width(4.dp))
                        Text(
                            text = viewState.item.rating.toString(),
                            overflow = TextOverflow.Ellipsis,
                            maxLines = 1,
                        )
                    }
                }
                Spacer(modifier = Modifier.height(2.dp))
                CampaignRow(campaignText = viewState.item.campaignText)
            }
        }
    }
}

@Composable
private fun CampaignRow(
    modifier: Modifier = Modifier,
    campaignText: String,
) = Row(modifier = modifier) {
    Image(
        painter = painterResource(androidx.ui.livedata.R.drawable.abc_ic_star_black_16dp),
        contentDescription = "",
        modifier = Modifier
            .wrapContentSize()
            .align(Alignment.CenterVertically)
            .padding(end = 4.dp)
    )
    Text(
        text = campaignText,
        overflow = TextOverflow.Ellipsis,
        maxLines = 1,
    )
}

I followed google guideline to fix performance issues.

  • I created Baseline profile
  • I tested on release build
  • I used key parameter on lazyColumn

but still happening performance issues. How can I prevent this?

1

There are 1 best solutions below

1
On

It's all right) This is a debag version issue. Compile the release version and everything will work smoothly