We have application with five tabs in Xamarin.Forms. iOS version is fine, but in Android performance on tab switch is really slow since the moment when we added five tab. When we remove any from tabs, then the performance is much better and tabs are opened almost immediately.
The problem is especially noticeable, when you go from first to last or from last to first.
New tab is selected immediately.
You have to wait few seconds to see new tab.
I've edited issue. Performed other test and it looks that this behaviour wasn't connected to particular page.
Hi, tried with our sample for tabs with multiple tabs CoreTabbedPage
as root of our controls gallery and didn't saw any big performance changes between 3 and 5 tabs. Can you please provide a repo so we look at the same thing.
Does this behave the same in all devices? how about on the emulator ?!
Thanks
Hi, It is difficult to make a repo, because it is my company application which has a lot of code, but after some investigation, now I know what is going on.
When app has 5 tabes and in Android you go to the fifth one, then layout on the first tab is destroyed or maybe better - recycled. So you have all data loaded earlier according to corresponding ViewModel, page is on place, but content is visually vanished.
When you return to first tab, controls placed here are recreating - on first tab we have a control (some kind of custom list with recycler view).
I tried to make a repro, on simple app, even with ListView and some cells, but I wasn't able to do it again.. Maybe it is connected with some memory managment in Android, or something..
I was digging with debugger, and now I know what it's going on.
I prepared very simple app (here is link to 7z: https://drive.google.com/file/d/1i_Dmppggo9OftUgMITDWF7yNP9pW95Nj/ )
with five tabs.
On first, second and five tab, there is a button with almost empty custom renderer:
public class ExtendedButtonRenderer : ButtonRenderer
{
public ExtendedButtonRenderer(Context context) : base(context)
{
System.Diagnostics.Debug.WriteLine($"ExtendedButtonRenderer:Constructor: {this.GetHashCode()}");
}
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
System.Diagnostics.Debug.WriteLine($"ExtendedButtonRenderer:OnElementChanged: {this.GetHashCode()} | {e.NewElement.AutomationId}");
}
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
System.Diagnostics.Debug.WriteLine($"ExtendedButtonRenderer:Dispose: {this.GetHashCode()}");
}
}
Now look on this navigation scenario:
[0:] ExtendedButtonRenderer:Constructor: 213320171
[0:] ExtendedButtonRenderer:OnElementChanged: 213320171 | FirstPageButton
[0:] ExtendedButtonRenderer:Constructor: 149047033
[0:] ExtendedButtonRenderer:OnElementChanged: 149047033 | SecondPageButton
SecondTab
[0:] ExtendedButtonRenderer:Constructor: 266513020
[0:] ExtendedButtonRenderer:OnElementChanged: 266513020 | FifthPageButton
FifthTab
[0:] ExtendedButtonRenderer:Dispose: 213320171
FirstTab
[0:] ExtendedButtonRenderer:Constructor: 16586460
[0:] ExtendedButtonRenderer:OnElementChanged: 16586460 | FirstPageButton
[0:] ExtendedButtonRenderer:Dispose: 266513020
FifthTab
[0:] ExtendedButtonRenderer:Constructor: 266924335
[0:] ExtendedButtonRenderer:OnElementChanged: 266924335 | FifthPageButton
[0:] ExtendedButtonRenderer:Dispose: 16586460
FourthTab
[0:] ExtendedButtonRenderer:Constructor: 224530542
[0:] ExtendedButtonRenderer:OnElementChanged: 224530542 | FirstPageButton
SecondTab
// Nothing
FirstTab
[0:] ExtendedButtonRenderer:Dispose: 266924335
The results are quite suprising. It looks like that there is something like 'tabs window' and it is limited to 3 tab neigbour tabs in both directions?
When you run app, then there are attached renderers for first four tabs (first + next three). When you go to second tab, the window is moving and app creates renderer for fith tab.
When you go on fifth tab, then renderers from first tab are destroyed. When after this you go from fifth to first then fifth page renderers are destoyed and renderers from first tab are recreated.
When you are on tabs from range 2-4, then are renderers are available.
One important thing - pages on tabs are never destroyed.
Tester on Xamarin.Forms 3.2 and 3.4
You might find that this slows down the initial load of your app, but you can adjust the number of tabs that Android preloads for you with this platform specific:
Thanks!
Most helpful comment
I was digging with debugger, and now I know what it's going on.
I prepared very simple app (here is link to 7z: https://drive.google.com/file/d/1i_Dmppggo9OftUgMITDWF7yNP9pW95Nj/ )
with five tabs.
On first, second and five tab, there is a button with almost empty custom renderer:
Now look on this navigation scenario:
The results are quite suprising. It looks like that there is something like 'tabs window' and it is limited to 3 tab neigbour tabs in both directions?
When you run app, then there are attached renderers for first four tabs (first + next three). When you go to second tab, the window is moving and app creates renderer for fith tab.
When you go on fifth tab, then renderers from first tab are destroyed. When after this you go from fifth to first then fifth page renderers are destoyed and renderers from first tab are recreated.
When you are on tabs from range 2-4, then are renderers are available.
One important thing - pages on tabs are never destroyed.
Tester on Xamarin.Forms 3.2 and 3.4