It blown my head for 3 days, while I tried to find a solution and found that the issue comes because TabView recreates every tab after it becomes inactive which leads to huge freeze if you have some heavy components.
I have 5 tabs. In the second one I have a list view with 100 rows.
At first load, all tabs are showing very fast.
If i open tab 4 or 5, next time i open tab 2, i have a freeze of 2 seconds. I saw that the list view is recreated every time after the tab becomes inactive. And it becomes inactive only when i open a tab which is not the next or previous one.
If i switch from 1 or 3 to second tab(and I haven't switched before to 4 or 5) the change is instant. But if I switch to 4 or 5, the next time I open a tab with ListView the switch takes minimum 2 seconds.
The switch to the other tabs(without a list views) doesn't need more than 300-400ms even if they were inactive before. Tested with both ListView and RadListView. And I use async pipes right now.
If I remove the ListView component every tab switch takes maximum 300-400ms for reload.
By the way, I use my Samsung Galaxy S7 for testing, and I didn't had any other application hanging like this since i bought it(6months ago)
Yes, i checked documentation, stackoverflow, all related nativescript issues and all the internet related blog posts.
I need to prevent recreation of TabView content after the tab becomes inactive, because the switch to a tab with a ListView freezes de UI for 2 seconds.
Android
Plugin(s):
@angular/common: 2.0.1
@angular/compiler: 2.0.1
@angular/core: 2.0.1
@angular/forms: 2.0.1
@angular/http: 2.0.1
@angular/platform-browser: 2.0.1
@angular/platform-browser-dynamic: 2.0.1
@angular/platform-server: 2.0.1
@angular/router: 3.0.1
nativescript-angular: 1.0.1
nativescript-drop-down: ^1.3.2
nativescript-intl: 0.0.4
nativescript-statusbar: ^1.0.0
nativescript-telerik-ui: ^1.4.1
angular app with 5 tabs(tabview), and insert one ListView/RadListView in one of the tabs, then switch the tabs. Everytime when you switch to the tab with the ListView(from a tab which is not next one or previous one) you get a freeze of 2 seconds.
I will try to make a small demo with the problem soon.
Hi @adisoftbn,
thank you for your interest in NativeScript.
I reviewed your scenario , however this is something related with the platform. In your case when you have 5 TabView items and has selected the second one, where is the ListView, the next and the previous items has been loaded on the memory and the navigation between the first three items will be instant. However if you have selected the fifth item and return back to this with the ListView, the ListView will always be recreated.
I hope this information helps.
Regards,
@tsonevn
Hey @tsonevn,
Doesn't this help: http://stackoverflow.com/questions/28494637/android-how-to-stop-refreshing-fragments-on-tab-change ?
I saw a lot of android apps that dont have this problem.
Best regards,
Adrian Nicoara
Hi @adisoftbn,
thank you for the additional info.
We will research what is causing slow navigation between the items inside the TabView. I am attaching link to a sample project where this issue could be reproduced. As a temporary solution you could setOffscreenPageLimit method to increase the items that will be loaded in the memory for android.
Workaround
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
<TabView id="tabViewContainer" selectedIndex="{{index}}" loaded="loadedTabView">
<TabView.items>
<TabViewItem title="Tab 1">
<TabViewItem.view>
<Label text="This is Label in Tab 1" />
</TabViewItem.view>
</TabViewItem>
<TabViewItem title="Tab 2">
<TabViewItem.view>
<GridLayout>
<ListView items="{{ source }}" loaded="onLoaded" itemLoading="onItemLoading" itemTap="onItemTap">
<ListView.itemTemplate>
<StackLayout>
<Label text="{{title}}" textWrap="true" />
</StackLayout>
</ListView.itemTemplate>
</ListView>
</GridLayout>
</TabViewItem.view>
</TabViewItem>
<TabViewItem title="Tab 3">
<TabViewItem.view>
<Label text="This is Label in Tab 3" />
</TabViewItem.view>
</TabViewItem>
<TabViewItem title="Tab 4">
<TabViewItem.view>
<Label text="This is Label in Tab 4" />
</TabViewItem.view>
</TabViewItem>
<TabViewItem title="Tab 5">
<TabViewItem.view>
<Label text="This is Label in Tab 5" />
</TabViewItem.view>
</TabViewItem>
</TabView.items>
</TabView>
</Page>
import { EventData } from 'data/observable';
import { Page } from 'ui/page';
import { HelloWorldModel } from './main-view-model';
import {ObservableArray} from "data/observable-array";
import {Observable, PropertyChangeData} from "data/observable";
import {TabView} from "ui/tab-view";
import {isAndroid} from "platform"
// Event handler for Page "navigatingTo" event attached in main-page.xml
export function navigatingTo(args: EventData) {
// Get the event sender
let page = <Page>args.object;
let array = new ObservableArray();
let observable = new Observable();
observable.set("source", array);
for(var i=0; i<500; i++){
array.push({title:"title "+i});
}
page.bindingContext = observable;
}
export function loadedTabView(args:EventData){
let tabview:TabView = <TabView>args.object;
console.log((<any>tabview)._viewPager);
if(isAndroid){
(<any>tabview)._viewPager.setOffscreenPageLimit(3);
}
}
Angular
app.component.html
<TabView #tabview (loaded)="tabviewloaded($event)">
<StackLayout *tabItem="{title: 'Tab1'}">
<Label text="This is Label in Tab 1"></Label>
</StackLayout>
<StackLayout *tabItem="{title: 'Tab2'}">
<ListView [items]="myItems" (itemTap)="onItemTap($event)">
<template let-item="item" let-i="index" let-odd="odd" let-even="even">
<StackLayout [class.odd]="odd" [class.even]="even">
<Label [text]='"index: " + i'></Label>
<Label [text]='"[" + item.id +"] " + item.name'></Label>
</StackLayout>
</template>
</ListView>
</StackLayout>
<StackLayout *tabItem="{title: 'Tab3'}">
<Label text="This is Label in Tab 3"></Label>
</StackLayout>
<StackLayout *tabItem="{title: 'Tab4'}">
<Label text="This is Label in Tab 4"></Label>
</StackLayout>
<StackLayout *tabItem="{title: 'Tab5'}">
<Label text="This is Label in Tab 5"></Label>
</StackLayout>
</TabView>
app.component.ts
import {Component, OnInit} from "@angular/core";
import {isAndroid} from "platform";
import {TabView} from "ui/tab-view"
class DataItem {
constructor(public id: number, public name: string) { }
}
@Component({
selector: "my-app",
templateUrl: "app.component.html",
})
export class AppComponent {
public myItems: Array<DataItem>;
private counter: number;
constructor() {
}
ngOnInit(){
this.myItems = [];
this.counter = 0;
for (var i = 0; i < 500; i++) {
this.myItems.push(new DataItem(i, "data item " + i));
this.counter = i;
}
}
public onItemTap(args) {
console.log("------------------------ ItemTapped: " + args.index);
}
public tabviewloaded(args){
var tabview:TabView = <TabView>args.object;
if(isAndroid){
(<any>tabview)._viewPager.setOffscreenPageLimit(3);
}
}
}
Regards,
@tsonevn
Thank you 馃憤
You rock :D works like a charm!! 100% fluid!!
Changed the value to 4 to be able to test it more further with memory consumption and so on.
Best regards,
Adrian Nicoara
androidOffscreenTabLimit property doesn't work fine when position is bottom. More detail is in this issue.
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.
Most helpful comment
Hi @adisoftbn,
thank you for the additional info.
We will research what is causing slow navigation between the items inside the
TabView. I am attaching link to a sample project where this issue could be reproduced. As a temporary solution you couldsetOffscreenPageLimitmethod to increase the items that will be loaded in the memory for android.Workaround
main-page.xml
Angular
app.component.html
app.component.ts
Regards,
@tsonevn