Nativescript: Application crashing when loading too much Images in a ListView.

Created on 5 Oct 2017  路  3Comments  路  Source: NativeScript/NativeScript

Did you verify this is a real problem by searching [Stack Overflow]

Yes

Tell us about the problem

In my home screen, i have a lot of images (Like the images below)
Images here. (Imgur)

The problem is, that sometimes the app just get crashed after a few seconds (more often on the first initialization). Normally it occurs when all the images are loading (All of them are remote images) or when the user is scrolling down between all the sections.

I've installed the plugin nativescript-we-image-cache to see if i could improve this issue, but it keeps happening. With this plugin, all i've got is to improve the fluidity of the application and the crashes are less frequent.

When there's not too much images on the ListView, it doesn't crash.

There is some way to fix this? I really need all those images on the application home page.
All of them are really tiny in size, so i think the problem is that all that load of images at the same time are crashing the application.

Which platform(s) does your issue occur on?

iOS/Android/Both
Both

Please provide the following version numbers that your issue occurs with:

  • CLI: 3.2.1
  • Cross-platform modules: ^3.2.0
  • Runtime(s):
    tns-android: version 3.2.0

  • Plugin(s): "dependencies": { "@angular/animations": "~4.2.0", "@angular/common": "~4.2.0", "@angular/compiler": "~4.2.0", "@angular/core": "~4.2.0", "@angular/forms": "~4.2.0", "@angular/http": "~4.2.0", "@angular/platform-browser": "~4.2.0", "@angular/router": "~4.2.0", "nativescript-angular": "~4.2.0", "nativescript-couchbase": "^1.0.18", "nativescript-local-notifications": "^1.2.2", "nativescript-ngx-fonticon": "^2.2.3", "nativescript-pdf-view": "^2.0.1", "nativescript-plugin-firebase": "^4.1.1", "nativescript-social-share": "^1.4.0", "nativescript-telerik-ui": "^3.0.4", "nativescript-theme-core": "~1.0.2", "nativescript-web-image-cache": "^4.2.2", "reflect-metadata": "~0.1.8", "rxjs": "~5.4.2", "tns-core-modules": "^3.2.0", "zone.js": "~0.8.2" },

Please tell us how to recreate the issue in as much detail as possible.

  1. Create a RadListView inside a new Component.
  2. Create the template with an StackLayout, that contains an ScrollView (Horizontal) with another StackLayout, this StackLayout is container of a lot of images generated dynamically from a service. Every image has to be from an remote source.
  3. Wait the images to load. In some cases, the app will crash.

Is there code involved? If so, please share the minimal amount of code needed to recreate the problem.

home.component.html

<RadListView [items]="portals" pullToRefresh="true">

                    <ng-template let-item="item">

                        <StackLayout [visibility]="(item.enabled || selectedMode != 'category') ? 'visible' : 'collapse'">

                                <StackLayout [ngSwitch]="item.visible" orientation="horizontal" horizontalAlignment="left" class="titleLayout" (tap)="item.visible = !item.visible">

                                    <Label class="categoryTitle" [text]="item.name"></Label>

                                    <Label class="fa categoryIcon" *ngSwitchCase="true" [text]="'fa-chevron-down' | fonticon"></Label>

                                    <Label class="fa categoryIcon" *ngSwitchDefault [text]="'fa-chevron-up' | fonticon"></Label>

                                </StackLayout>

                                <ScrollView *ngIf="!item.visible" orientation="horizontal" class="scrollCategory">

                                    <StackLayout orientation="horizontal" class="stackCategory">

                                            <WebImage stretch="fill" *ngFor="let portal of item.portals" [src]="portal.img" class="portal" (tap)="gotoPortal(item.id, portal.id)"></WebImage>

                                    </StackLayout>

                                </ScrollView>

                                <WrapLayout *ngIf="item.visible">

                                        <WebImage stretch="fill" *ngFor="let portal of item.portals" [src]="portal.img" class="portal" (tap)="gotoPortal(item.id, portal.id)"></WebImage>

                                </WrapLayout>

                        </StackLayout> 

                    </ng-template>

                </RadListView>

home.component.ts

(Relevant parts of the code)
```
@Component({
selector: "medios-home",
moduleId: module.id,
templateUrl: "home.component.html",
styleUrls: ['home.component.css']
})
export class HomeComponent implements OnInit, OnDestroy {
...

private _portals:ObservableArray;
public get portals():ObservableArray {
return this._portals;
}

ngOnInit(): void {
this.initPortals();
this._changeDetectionRef.detectChanges();
}

initPortals() {
this.portalsService.getPortalsBy('category')
.subscribe((res) => {
this._portals = this.portalsService.organizeCategories(res);
this.loading = false;
});
}

...

question

Most helpful comment

@Aegm91 Try to use the Image module and follow the best practices described in this article.
You can set decodeWidth and decodeHeight properties for Android and also set loadAsync to prevent the UI from being blocked while your images are loading.

Another thing I have noticed is that you are using ngFor Angular directive to load the multiple photos. The ngFor is not performance optimized and should be used to load only a small portion of repeating items. For heavier list (in your case- a list of multiple images) you should always use ListView or RadListView as they are optimized (recycling and virtualization) to handle larger and "heavier" lists. See this blog post for more information about why to use ListView instead of ngFor

All 3 comments

@Aegm91 Try to use the Image module and follow the best practices described in this article.
You can set decodeWidth and decodeHeight properties for Android and also set loadAsync to prevent the UI from being blocked while your images are loading.

Another thing I have noticed is that you are using ngFor Angular directive to load the multiple photos. The ngFor is not performance optimized and should be used to load only a small portion of repeating items. For heavier list (in your case- a list of multiple images) you should always use ListView or RadListView as they are optimized (recycling and virtualization) to handle larger and "heavier" lists. See this blog post for more information about why to use ListView instead of ngFor

THANK YOU! I've followed all the advices on the articles you sended and it worked like a charm!

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings