HelloCW
HelloCW

Reputation: 2295

Why is the UI made by Android Jetpack Compose loaded so slow?

I create an app with Code A made by Android Jetpack Compose, It shows a blank UI long time before main UI is displayed, you can see Image A

I learned some sample project, such as the official sample project Crane.

So I modify Code A as Code B based Crane, I hope Code B to display a Loading UI quickly before main UI is displayed, but I still find it shows a blank UI long time before main UI is displayed with Code B.

BTW, I find the sample project Crane also shows a blank UI long time before main UI is displayed, you can see Image B.

A: How can I show a Loding UI quickly before main UI is displayed?

B: I can't understand Code B fully, why does the Loding UI dismiss automatically? does it due to the API function MutableTransitionState?

C: In Code B, even if I set val SplashWaitTime: Long = 10000000, I find the Loding UI dismissed about 2 sencond later just like I set val SplashWaitTime: Long = 2000, why?

Code A

@AndroidEntryPoint
class ActivityMain : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SoundMeterTheme {
                Surface(color = MaterialTheme.colors.background) {                   
                    NavGraph()
                }
            }
        }
    }
}

Image A

enter image description here

Code B

@AndroidEntryPoint
class ActivityMain : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SoundMeterTheme {
                Surface(color = MaterialTheme.colors.background) {
                    val transitionState = remember { MutableTransitionState(SplashState.Shown) }
                    LandingScreen(
                        onTimeout = { transitionState.targetState = SplashState.Completed }
                    )
                    NavGraph()
                }
            }
        }
    }    
}


private const val SplashWaitTime: Long = 2000
enum class SplashState { Shown, Completed }

@Composable
fun LandingScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
    Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {       
        val currentOnTimeout by rememberUpdatedState(onTimeout)

        LaunchedEffect(Unit) {
            delay(SplashWaitTime)
            currentOnTimeout()
        }
       Text("Loading..")
    }
}

Image B

enter image description here

Upvotes: 7

Views: 7550

Answers (2)

Yasan Glass
Yasan Glass

Reputation: 1314

Compose is very slow on debug builds, enable optimization (minifyEnabled true) and test UI performance on release builds only.

Upvotes: 3

Thracian
Thracian

Reputation: 67179

You should test for performance in release build mode with R8 enabled

   release {

       minifyEnabled true

   }

You can read more about it here or here in official document about performance, and first load of Compose might be slow and it's advised to use baseline profiles

Use a baseline profile

Compose is distributed as a library, instead of being part of the Android platform. This approach lets us update Compose frequently and support older Android versions. However, distributing Compose as a library imposes a cost. Android platform code is already compiled and installed on the device. Libraries, on the other hand, need to be loaded when the app launches, and interpreted just-in-time when the functionality is needed. This can slow the app on startup, and whenever it uses a library feature for the first time.

You can improve performance by defining baseline profiles. These profiles define classes and methods needed on critical user journeys, and are distributed with your app's APK. During app installation, ART compiles that critical code ahead-of-time, so it's ready for use when the app launches.

It's not always easy to define a good baseline profile, and because of this Compose ships with one by default. You might not have to do any work to see this benefit. However, if you choose to define your own profile, you might generate one that doesn't actually improve your app's performance. You should test the profile to verify that it's helping. A good way to do that is to write Macrobenchmark tests for your app, and check the test results as you write and revise your baseline profile. For an example of how to write Macrobenchmark tests for your Compose UI, see the Macrobenchmark Compose sample.

Upvotes: 6

Related Questions