I am using LazyColumn
in my project and it is very slow on scrolling the items. I created a very small project to show what is the problem in my code. It scroll smoothy on Pixel
, OnePlus
devices, but it's laggy on Samsung
device. So what are the things we can improve in this code.
Problem
You can see the scroll is laggy in LazyColumn.
@Composable
fun SeeAllView(
viewModel: MainActivityViewModel,
handleItemSelection: (TestDataModel) -> Unit,
ctaAction: (CurrentModel) -> Unit,
) {
LazyColumn(
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(20.dp),
) {
items(viewModel.itemList, key = { it.index }) { item ->
ListContent(false, item, ctaAction, handleItemSelection)
}
}
}
@Composable
fun ListContent(
useSpaceView: Boolean = true,
myTestDataItem: TestDataModel,
ctaAction: (CurrentModel) -> Unit,
handleItemSelection: (TestDataModel) -> Unit,
) {
val name = myTestDataItem.name
val image = myTestDataItem.iconUrl
val summary = myTestDataItem.summary
val currentModel = myTestDataItem.eventModel.currentModel
AnimatedVisibility(visible = useSpaceView) {
Spacer(Modifier.height(20.dp))
}
ListItem(name, image, summary, currentModel, ctaAction) {
handleItemSelection(myTestDataItem)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ListItem(
name: String,
image: Int,
summary: String,
currentModel: CurrentModel,
ctaAction: (CurrentModel) -> Unit,
openBottomSheet: () -> Unit
) {
Card(
modifier = Modifier
.fillMaxSize(),
colors = CardDefaults.cardColors(containerColor = Color.White),
shape = RoundedCornerShape(20.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp),
onClick = { openBottomSheet() },
) {
Column(
modifier = Modifier.padding(20.dp)
) {
PanelHeaderView(name, image)
SummaryView(summary)
CtaView(
modifier = Modifier
.align(Alignment.End),
currentModel,
ctaAction,
)
}
}
}
@Composable
private fun PanelHeaderView(testName: String, testImage: Int) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
modifier = Modifier.weight(0.1f),
painter = painterResource(testImage),
contentDescription = null
)
AnimatedVisibility(
visible = testName.isNotEmpty(),
modifier = Modifier
.weight(0.8f)
.padding(start = 20.dp),
) {
Text(
text = testName,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = null,
tint = Color.Black
)
}
}
@Composable
private fun SummaryView(summary: String) {
AnimatedVisibility(visible = summary.isNotEmpty()) {
AndroidView(
modifier = Modifier.padding(top = 20.dp),
factory = { context -> TextView(context) },
update = { textView ->
with(textView) {
text = HtmlCompat.fromHtml(summary, HtmlCompat.FROM_HTML_MODE_COMPACT)
setTextColor(ContextCompat.getColor(context, R.color.black))
setTextSize(TypedValue.COMPLEX_UNIT_PX, 60F)
}
}
)
}
}
@Composable
private fun CtaView(
modifier: Modifier,
currentModel: CurrentModel,
ctaAction: (CurrentModel) -> Unit,
) {
AnimatedVisibility(
modifier = modifier,
visible = currentModel.showCtaAction
) {
ClickableText(
modifier = Modifier.padding(top = 20.dp),
text = AnnotatedString(currentModel.actionTitle),
onClick = { ctaAction(currentModel) }
)
}
}
I am using latest version of compose, you can find the gradle.kt
dependencies {
implementation 'androidx.core:core-ktx:1.10.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core-ktx:1.10.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
def composeBom = platform "androidx.compose:compose-bom:2023.05.01"
implementation composeBom
androidTestImplementation composeBom
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.foundation:foundation"
implementation "androidx.compose.foundation:foundation-layout"
implementation "androidx.compose.material:material"
implementation "androidx.compose.material3:material3"
implementation "androidx.compose.runtime:runtime"
implementation "androidx.compose.runtime:runtime-livedata"
implementation "androidx.compose.ui:ui-tooling"
implementation "androidx.compose.ui:ui-tooling-preview"
implementation "androidx.lifecycle:lifecycle-viewmodel-compose"
implementation "androidx.activity:activity-compose:1.7.2"
androidTestImplementation "androidx.compose.ui:ui-test"
androidTestImplementation "androidx.compose.ui:ui-test-junit4"
debugImplementation "androidx.compose.ui:ui-test-manifest"
implementation "io.insert-koin:koin-android:3.4.0"
implementation "io.insert-koin:koin-androidx-workmanager:3.4.0"
implementation "io.insert-koin:koin-androidx-compose:3.4.3"
}
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val viewModel by viewModel<MainActivityViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupViewModel()
setContentView(binding.root)
}
private fun setupViewModel() {
viewModel.requestCompleteLiveData.observe(this) { dataReturned ->
if (dataReturned) {
setupView()
}
}
viewModel.createData()
}
private fun setupView() {
binding.composeView.setContent {
AppBarScaffold(R.string.app_name, true) {
SeeAllView(viewModel, {}, {})
}
}
}
}
You can find the whole project in here github.
Thanks