Reputation: 269
I have a function that fetches data from an API and displays that data. I want to show a circular progress bar on the screen until that page is ready.
fun Preview(Number: String) {
var selected by remember { mutableStateOf<Train?>(null) }
//var isLoading = remember { mutableStateOf(true) }
LaunchedEffect(key1 = Unit) {
//Simulate an API delay
delay(1000)
selected = data from API
}
if (selected != null) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
beyondBoundsPageCount = 2
)
{ index ->
selected?.get(index)?.let {
PagerContent(it)
}
}
} else {
Column(
Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressIndicator(color = Color.Blue)
Spacer(modifier = Modifier.height(10.dp))
Text(text = "Loading Please Wait...")
}
}
}
This code shows a progress bar then it kind of hangs. I think wait for PagerContent() to get loaded. I want it to keep showing the progress bar until PagerContent() is loaded/data is displayed on the page.
Upvotes: 0
Views: 277
Reputation: 15589
The UI runs on a single thread, the main thread. You can launch coroutines, but in general these can't call composable functions. That also means that the UI cannot be constructed asynchronously. Therefore you can either display a frame of an animation or construct some other part of the UI, not both at the same time. When constructing some UI element takes too long the next animation frame cannot be executed fast enough so the animation seems to "hang".
The real question that you must ask yourself is why PagerContent
even takes so long to execute that it is noticable.
Compose functions are intended to execute very fast because they are executed everytime a recomposition takes place. Recompositions in general can occur as often as every frame, which will be usualy at least 60 times a second. "Can occur" means that's the worst case, and usually you will have far less recompositions. Nevertheless you will want your composable functions to still execute as fast as possible to prevent the kind of jank you experienced.
What you need to do is make PagerContent
faster. Since you didn't share the code of PagerContent
we can only speculate why it takes so long to execute. Possible reasons are:
This list is not exhaustive but you probably get the gist: Move everything that isn't directly related to creating UI elements (which must be executed on the main thread) out of PagerContent
and into the view model while also executing it on another, more appropriate dispatcher.
When PagerContent
is fast enough that its execution time isn't noticeable anymore the problem you described in your question will also be gone.
Upvotes: 0
Reputation: 1
I think you should try seperating IF and ELSE Condition statements and check.
if (selected != null) {
HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(),
beyondBoundsPageCount = 2
)
{ index ->
selected?.get(index)?.let {
PagerContent(it)
}
}
}
if (selected == null) {
Column(
Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressIndicator(color = Color.Blue)
Spacer(modifier = Modifier.height(10.dp))
Text(text = "Loading Please Wait...")
}
}
Upvotes: -1