Poor ListView performance on Gluon

2020-02-02 01:10发布

问题:

I have a custom ListCell implementation, shown in the picture below.

The left side, which represents the date, consisting of 3 labels, put in a VBox and the "CounterContent" consisting of the counter, with a TextField for each digit, contained in a HBox, and two Hboxes containing labels for kWh, kWh/day and so on. And that seem to be just too much, to be running performantly.

I've tried to load the data in a background task, showing a progress indicator, while the task is running, but unlike on desktop, on android the performance is very poor. Whenever I switch to the listview, the garbage collection kicks in, and blocks the ui thread, so that the progress indicator never shows up.

I've tried it on a Huawei Y-300, Android 4.1.1, javafxports 8.60.6 (because javafxports 8.60.7 causes a bug, that makes TextField unusable), and on a Samsung S5 mini, Android 5+. On the Samsung phone the performance in general is way better, just like expected, because of the Ahead-of-Time compilation I guess, but there is still the garbage collection issue. Furthermore after the listview has been populated with cells, the scrolling is not very smooth.

Is the listcell to complex or what else could be the matter for the poor performance?

UPDATE:

After running a lot of tests it seems the unsmooth scrolling is not caused by performance problems. At least on the S5 (javafxports 8.60.7).

I removed all css styling, and replaced the textfields by a single label (the counter node is already a custom control(forgot about that), which lays out the textfields in 2 Regions(not HBoxes) and the nodes of the ListCell are instantiated in the constructor). Furthermore I switched the ListView for a CharmListView and set android.monocle.input.touchRadius=1.

None of these steps resulted in considerable improvement.

Just to clarify: In contrast to the Huawei phone, the scrolling on the S5 and android 5+ is usable, but it's not very smooth, which makes for a unsatisfactory user experience.

On the Huawei (javafxports 8.60.6), changing the counter textfields for a label, gave a significant improvement, but not to the point where the scrolling became usable. Until I set this magical experimental switch: gluon.experimental.performance=true, which makes the listview scrolling lightning fast(after a little warmup delay), but still not really smooth.

回答1:

There are many reasons why the performance of a complex scene is reduced, so this is just a list of possible ideas that might help improving it, in any order.

ListCell

For starters, the number of nodes in the cell is really high. Notice that every single scroll you make means the full rendering of the virtual flow that holds the visible cells. And for every cell, that means recreating its content all over again.

Without viewing your code I can't tell, but you should avoid creating new instances of every node in the cell all the time, by having just one single instance, and in the updateItem method only change the content of the nodes.

Have a look at this sample. The NoteCell class is a custom cell, where a ListTile is used.

Number of nodes

Have you tried using just a Label to replace the 8 textfields and 3 boxes?

Cache

If you use images downloaded from Internet, use Gluon Charm Down Cache to avoid the same image being downloaded over and over again.

Have a look at this sample. Without the cache, even on desktop the performance is really affected.

Also use the JavaFX built-in cache for any node, trying different cache strategies.

CSS

Complex CSS requires long CPU time. Try to simplify it. Even you can remove the whole CSS for a quick test. Then decide what you may or may not use.

The same goes for animations: Avoid animations, transitions or even CSS effects, if possible.

Custom Control

The counter complex node could probably be replaced by a custom control that optimizes the rendering.

CharmListView

Have you tried using the Gluon Charm CharmListView control instead of the ListView?

There's a new experimental flag that you can use to test a possible optimization that might improve performance while scrolling the list. Set gluon.experimental.performance=true on the java.custom.properties file, and give it a try.

JavaFXPorts version

You mentioned you are using 8.60.6 because of the TextField bug. In this case, are your TextField nodes editable? If not, I'd suggest replacing them with other nodes and running with 8.60.7, since it contains a lot of performance improvements.

Performance tools

Use performance tools like Monitor and use its profiling options so you can trace down any possible bottle neck.

CPU

Last but not least: your mobile device specs are always critical.

Trying to render a complex scene on a Cortex A5, given that "it is the smallest, lowest cost and lowest power ARMv7 application processor", or using a very old Android 4.1.1, can't perform as well as running it on a brand new device with higher specs.

As you also mentioned, running on a Cortex A7 performs "way better". Have a look at this comparison, and find the right architecture for the job.

Anyway, there's always room for improvement, and a lot of effort is put into it. Your feedback is always welcome.