Hi guys, I already discuss in this <chat> for slow...
# compose
k
Hi guys, I already discuss in this chat for slow performance of scrolling in Samsung device. I am sharing my code, please have a look and guide me if we can improve this. You can find the whole project in here.
Copy code
@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) }
        )
    }
}
MainActivity
Copy code
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, {}, {})
            }
        }
    }
}
t
what i have found when dealing with poor performance on lists in Android is that you should not perform any processing on the data being displayed. the best performance is always obtained by simply reading the data from your local database and displaying it directly, i believe you will find the issue is being caused by this line of code
Copy code
HtmlCompat.fromHtml(summary, HtmlCompat.FROM_HTML_MODE_COMPACT)
k
I removed this code but still have the problem
My original data is coming from the server. So first filter it and save it in the local database. Then retrieved the data from the database and then show ?
t
yes, thats the approach i always take, when my application opens for the first time i synch all the data from my server,
then each screens simply retrieves from the local database you need to preprocess any data items that require it when you persist it to your local database
k
I cannot store data in the local database. Data is very sensitive in my side
t
oh dear 😞
k
Data changes accordingly to user requirements.
t
why not use in memory sqlite database then ?
k
Do you have an example for this ?
I heard about sqlite database but not memory related stuff.
t
use Room on android and simply build your db like this...
Room.inMemoryDatabaseBuilder(appContext, MyMemoryDatabase::class.java)
.addMigrations(
Migration_ONE_to_TWO(),
Migration_TWO_to_THREE(),
Migration_THREE_to_FOUR(),
Migration_FOUR_to_FIVE(),
)
.addCallback(callback)
.build()
k
Ok I'll try this one
k
Thank you so much. I'll try and get back to you
t
if you have never used room before start with a code lab then once you have that working simply change it to use an in memory db 😄
one step at a time 😉
k
Sure, thanks for advice
t
i hope it helps you 😄
s
Does the example have the same poor performance characteristics on Sumsung devices? I haven't done much interop with the Android view system from compose. How often is
update
in
SummaryView
called? If the text calculation is expensive. you can
remember
it outside of the
AndroidView
. That section is the only thing that looks suspicious to me. You could try migrating
SummaryView
to compose instead of using the interop.
k
Yes these example is very slow in Samsung device.
Sorry I didn't get it
How often is update in SummaryView called?
s
k
Ok lemme try to remove intero api and use normal
s
I'm going to test it in the emulator, then go grab a samsung tablet.
k
See this video when we scroll the items https://youtube.com/shorts/M-8MNr7JkLw?feature=share
In the middle of scrolling it laags, and then it normal and then start lagging again
No luck I tried to use normal
Text
instead of
AndroidView
. It still have slow scrolling issue
s
It's not the
SummaryView
. I still have the issue when making that a no-op.
k
What is no-op?
s
no operation. I deleted the contents of the function and it's still stuttering.
k
yeah, I don't understand what is the main reason of this
s
I think it might be
AnimatedVisibility
causing the issues. After removing them, it's a bit jittery, but seems usable for a debug build.
k
Did you removed all
AnimatedVisibility
?
s
k
I am having same issue if I used
AnimatedVisibility
or not.
s
I think maybe I wasn't swiping fast enough. It seems like the simpler you make it, the faster you need to swipe to get it to stutter.
Anyway, even with the most basic list, I can get it to stutter. So I'm not sure there's much to do here. Maybe it's worth filing a bug report.
For what it's worth, it only happens with
LazyColumn
,
Column
scrolls smoothly.
k
Already report bug for
LazyColumn
.
Thanks Sean for your help. I really appreciate it.
s
No problem. Good luck.
I tested on an SM-X200 (samsung galaxy tab A8). It's not a high end device, but it should be able to handle something like this without issue.
k
yes
Column
works much faster than
LazyColumn
t
Can you check what happens when you change all Text views to use modifier fillMaxWidth (I saw in the past problems when the text width must be calculated for each frame. Maybe try to do some things which avoid this.) Can you please check how big the image is you are displaying. And make sure it is not much bigger than the needed resolution.