Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack Compose Performance Issue that only occurs in multi module project

I have developed a quite complex keyboard layout in Jetpack Compose. Initially, the layout works fine and animations run very smoothly when pressign the keys. Unfortunately, after a few recompositions due to events the animations and everything becomes very slow and laggy. I have tried to sample Jave Method calls and I can only see that some function take a lot longer than usual.

Edit: I have been able to isolate the issue. I have discovered that the performance issue only appears in multi module projects. When I put the exact same compose code in the root app module the issue disappears.

I have created a project that reproduces the issue:

  • Mutli Module Project with performance issue
  • Single Module Project without performace issue

If you want to reproduce the issue in the multi module project you have to switch between the categories multiple times and then everything becomes very laggy

Example Video

Note: I know Jetpack Compose is still in alpha and this issue might be a bug in Jetpack Compose. But I want to make sure that it's not a bug of my code or a general limitation of Compose

like image 685
Yannick Avatar asked Jan 20 '21 21:01

Yannick


People also ask

Is jetpack compose slow?

Slow frame percentage: For compose-based layout, the slow frame rate came out to be 8.91% whereas it was 9.93% for XML-based layout. Like frozen frames, ~10 out of 100 frames would fall under the slow frame category for XML-based layout.

Is jetpack compose is stable?

Compose 1.2 includes a number of updates for Compose on Phones, Tablets and Foldables - it contains new stable APIs graduated from being experimental, and supports newer versions of Kotlin. We've already updated our samples, codelabs, Accompanist library and MDC-Android Compose Theme Adapter to work with Compose 1.2.

What is LazyColumn in jetpack compose?

A LazyColumn is a vertically scrolling list that only composes and lays out the currently visible items. It's similar to a Recyclerview in the classic Android View system.

What is mutableStateOf jetpack compose?

mutableStateOf creates an observable MutableState<T> , which is an observable type integrated with the compose runtime. Any changes to value will schedule recomposition of any composable functions that read value . In the case of ExpandingCard , whenever expanded changes, it causes ExpandingCard to be recomposed.

Is there a multi-module architecture for Android apps using jetpack compose?

We have just seen an approach to designing a scalable multi-module architecture for Android apps that use Jetpack Compose, including navigation. Below is the complete diagram that defines a structure of a single feature in the app using the described approach.

Does jetpack compose affect the APK and build performance?

Jetpack Compose accelerates UI development and makes Android engineers more productive. However, adding a new tool to a project requires some consideration as it can affect the APK, and build and runtime performance. In this section, we compare how two different apps were impacted when adding or migrating to Jetpack Compose:

How does jetpack compose update a frame?

As discussed in Jetpack Compose Phases, when Compose updates a frame, it goes through three phases: Composition: Compose determines what to show –it runs composable functions and builds the UI tree. Layout: Compose determines the size and placement of each element in the UI tree. Drawing: Compose actually renders the individual UI elements.

How does jetpack compose compare to traditional viewgroups?

Traditional ViewGroups have lots of expressiveness in their measure and layout APIs that make it easy to cause multiple layout passes. These multiple layout passes can cause exponential work if done at specific nested points in the view hierarchy. Jetpack Compose enforces a single layout pass for all layout composables via its API contract.


1 Answers

The solution is to use remember composable for Keyboard @Composable to prevent layouts computation during recomposition.

val refs: List<List<Pair<Key, ConstrainedLayoutReference>>> =
         remember {
             keyboard.map { row ->
                row.map {
                   it to createRef()
               }
          }
}

val modifier = remember { ... }

val modifierPressed = remember { ... }        

Source code: https://github.com/dautovicharis/example_compose-keyboard-multimodule/commits/main

like image 62
Haris Dautović Avatar answered Oct 19 '22 22:10

Haris Dautović