NativeScript-Vue rendering RadListView very slow under android and freeze the UI
Asked 07 September, 2021
Viewed 2.3K times
  • 53
Votes

I have a nativescript-vue app with the RadListView component to display data to the user. Each row of the list include multiple informations for the current item. When i tap on a button to load and show the list the UI freeze (fast hardware -> short; slow hardware -> long). I figured out that the code part to load/combine the data run very short but the nativescript-internal rendering or creation of the UI elements are the problem. The android console show the information

I/Choreographer: Skipped 430 frames!  The application may be doing too much work on its main thread.

Platform info:

  • tns-ios 5.2.0
  • tns-android 5.2.1
  • nativescript-ui-listview 6.2.0
  • tns-core-modules 5.3.1

Similar problem reports

I look at stackoverflow and github but the problems there (e.g. NativeScript Angular RadListView rendering extremely slowly) looks similar but the solutions not suitable for me.

I use the LinearListView (not Grid nor Stagged) and maybe in my real app i will be able to simplify the row elements from the list but in my sample app (look down) i use a simple row ui design.

Sample app

For a simpler and better report i created a sample app on the {N}-Playground. The app creates 10000 array elements and set them as source of the RadListView which has a Label, a Switch and an ActivityIndicator for every element.

<RadListView ref="listView" 
    for="alarm in alarms"
    layout="linear">
    <v-template>
        <StackLayout class="list-element" orientation="vertical" >
            <GridLayout columns="*, auto, auto" rows="*">
                <Label col="0" row="0">{{alarm.name}}</Label>
                <Switch col="1" row="0" :checked="alarm.active" />
                <ActivityIndicator col="2" row="0" :busy="alarm.active"/>
             </GridLayout>
             <Label class="list-element-divider"></Label>
         </StackLayout>
     </v-template>
</RadListView>

In the first step the 10000 elements will be generated in a temporary array:

loadData() {
    this.tmpAlarms = [];
    for (let i = 0; i <= 10000; i++) {
        this.tmpAlarms.push({
            name: "Hase " + i,
            active: i % 2 === 0,
        });
    }
}

With a second button set the temporary array as source:

setData() {
    this.alarms = this.tmpAlarms;
}    

Note: I use 10000 elements to make the problem visible even the sample app runs on a S9 or another high end smartphone.

The full source is runnable under https://play.nativescript.org/?template=play-vue&id=Td1GWR

A slightly different version with an ObservableArray instead of a plain array is under https://play.nativescript.org/?template=play-vue&id=5BXOFG

In both versions the data handling is fast but as soon the UI elements generated from the internal functions the UI will be frozen.

Sample: On my Nexus 7 2013 with Android 6.x the UI freeze nearly 6 seconds and no other apps running in background.

iOS

If i try the same apps on an iOS device (e.g. iPhone 7s) the rendering is very fast and the UI running smooth even so with the 10000 elements and more.

Ideas?

Have anyone an idea how i can speed up the rendering? If not is there a suggestion how i can build an animation (e.g. ActivityIndicator) to show the user that the device is working? At the moment when i put an ActivityIndicator on the UI the user can not see it because of the frozen UI.

1 Answer