Reduce overhead of pushing existing navigation stack (#672)
* Make StackCopy less awkward * Clean up comment * Update docs * Update docs * Replace SecondToLast with an arbitrarily deep Peek method * Update docs * Handle negative depths in Peek()
This commit is contained in:
Родитель
c468302e9d
Коммит
2c56d6211d
|
@ -213,28 +213,93 @@ namespace Xamarin.Forms.Core.UnitTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestStackCopy ()
|
||||
public async Task PeekOne()
|
||||
{
|
||||
var nav = new NavigationPage ();
|
||||
var nav = new NavigationPage();
|
||||
|
||||
bool signaled = false;
|
||||
nav.PoppedToRoot += (sender, args) => signaled = true;
|
||||
|
||||
var root = new ContentPage {Content = new View ()};
|
||||
var child1 = new ContentPage {Content = new View ()};
|
||||
var child2 = new ContentPage {Content = new View ()};
|
||||
var root = new ContentPage { Content = new View() };
|
||||
var child1 = new ContentPage { Content = new View() };
|
||||
var child2 = new ContentPage { Content = new View() };
|
||||
|
||||
await nav.PushAsync (root);
|
||||
await nav.PushAsync (child1);
|
||||
await nav.PushAsync (child2);
|
||||
await nav.PushAsync(root);
|
||||
await nav.PushAsync(child1);
|
||||
await nav.PushAsync(child2);
|
||||
|
||||
var copy = ((INavigationPageController)nav).StackCopy;
|
||||
|
||||
Assert.AreEqual (child2, copy.Pop ());
|
||||
Assert.AreEqual (child1, copy.Pop ());
|
||||
Assert.AreEqual (root, copy.Pop ());
|
||||
Assert.AreEqual(((INavigationPageController)nav).Peek(1), child1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PeekZero()
|
||||
{
|
||||
var nav = new NavigationPage();
|
||||
|
||||
bool signaled = false;
|
||||
nav.PoppedToRoot += (sender, args) => signaled = true;
|
||||
|
||||
var root = new ContentPage { Content = new View() };
|
||||
var child1 = new ContentPage { Content = new View() };
|
||||
var child2 = new ContentPage { Content = new View() };
|
||||
|
||||
await nav.PushAsync(root);
|
||||
await nav.PushAsync(child1);
|
||||
await nav.PushAsync(child2);
|
||||
|
||||
Assert.AreEqual(((INavigationPageController)nav).Peek(0), child2);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PeekPastStackDepth()
|
||||
{
|
||||
var nav = new NavigationPage();
|
||||
|
||||
bool signaled = false;
|
||||
nav.PoppedToRoot += (sender, args) => signaled = true;
|
||||
|
||||
var root = new ContentPage { Content = new View() };
|
||||
var child1 = new ContentPage { Content = new View() };
|
||||
var child2 = new ContentPage { Content = new View() };
|
||||
|
||||
await nav.PushAsync(root);
|
||||
await nav.PushAsync(child1);
|
||||
await nav.PushAsync(child2);
|
||||
|
||||
Assert.AreEqual(((INavigationPageController)nav).Peek(3), null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PeekShallow()
|
||||
{
|
||||
var nav = new NavigationPage();
|
||||
|
||||
bool signaled = false;
|
||||
nav.PoppedToRoot += (sender, args) => signaled = true;
|
||||
|
||||
var root = new ContentPage { Content = new View() };
|
||||
var child1 = new ContentPage { Content = new View() };
|
||||
var child2 = new ContentPage { Content = new View() };
|
||||
|
||||
await nav.PushAsync(root);
|
||||
await nav.PushAsync(child1);
|
||||
await nav.PushAsync(child2);
|
||||
|
||||
Assert.AreEqual(((INavigationPageController)nav).Peek(-1), null);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task PeekEmpty([Range(0, 3)] int depth)
|
||||
{
|
||||
var nav = new NavigationPage();
|
||||
|
||||
bool signaled = false;
|
||||
nav.PoppedToRoot += (sender, args) => signaled = true;
|
||||
|
||||
Assert.AreEqual(((INavigationPageController)nav).Peek(depth), null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void ConstructWithRoot ()
|
||||
{
|
||||
|
|
|
@ -7,7 +7,9 @@ namespace Xamarin.Forms
|
|||
{
|
||||
public interface INavigationPageController
|
||||
{
|
||||
Stack<Page> StackCopy { get; }
|
||||
Page Peek(int depth);
|
||||
|
||||
IEnumerable<Page> Pages { get; }
|
||||
|
||||
int StackDepth { get; }
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms.Internals;
|
||||
|
@ -61,17 +62,23 @@ namespace Xamarin.Forms
|
|||
|
||||
internal Task CurrentNavigationTask { get; set; }
|
||||
|
||||
Stack<Page> INavigationPageController.StackCopy
|
||||
Page INavigationPageController.Peek(int depth)
|
||||
{
|
||||
get
|
||||
if (depth < 0)
|
||||
{
|
||||
var result = new Stack<Page>(PageController.InternalChildren.Count);
|
||||
foreach (Page page in PageController.InternalChildren)
|
||||
result.Push(page);
|
||||
return result;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (PageController.InternalChildren.Count <= depth)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Page)PageController.InternalChildren[PageController.InternalChildren.Count - depth - 1];
|
||||
}
|
||||
|
||||
IEnumerable<Page> INavigationPageController.Pages => PageController.InternalChildren.Cast<Page>();
|
||||
|
||||
int INavigationPageController.StackDepth
|
||||
{
|
||||
get { return PageController.InternalChildren.Count; }
|
||||
|
|
|
@ -268,7 +268,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
navController.RemovePageRequested += OnRemovePageRequested;
|
||||
|
||||
// If there is already stuff on the stack we need to push it
|
||||
foreach (Page page in navController.StackCopy.Reverse())
|
||||
foreach (Page page in navController.Pages)
|
||||
{
|
||||
PushViewAsync(page, false);
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ namespace Xamarin.Forms.Platform.Android.AppCompat
|
|||
|
||||
Task<bool> OnPopViewAsync(Page page, bool animated)
|
||||
{
|
||||
Page pageToShow = ((INavigationPageController)Element).StackCopy.Skip(1).FirstOrDefault();
|
||||
Page pageToShow = ((INavigationPageController)Element).Peek(1);
|
||||
if (pageToShow == null)
|
||||
return Task.FromResult(false);
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
newNavController.RemovePageRequested += OnRemovePageRequested;
|
||||
|
||||
// If there is already stuff on the stack we need to push it
|
||||
foreach(Page page in newNavController.StackCopy.Reverse())
|
||||
foreach (Page page in newNavController.Pages)
|
||||
{
|
||||
PushViewAsync(page, false);
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
protected virtual Task<bool> OnPopViewAsync(Page page, bool animated)
|
||||
{
|
||||
Page pageToShow = ((INavigationPageController)Element).StackCopy.Skip(1).FirstOrDefault();
|
||||
Page pageToShow = ((INavigationPageController)Element).Peek(1);
|
||||
if (pageToShow == null)
|
||||
return Task.FromResult(false);
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ namespace Xamarin.Forms.Platform.WinPhone
|
|||
var platform = Element.Platform as Platform;
|
||||
if (platform != null)
|
||||
{
|
||||
if (e.Page == ((INavigationPageController)Element).StackCopy.LastOrDefault())
|
||||
if (e.Page == ((INavigationPageController)Element).Pages.FirstOrDefault())
|
||||
((IPageController)e.Page).IgnoresContainerArea = true;
|
||||
e.Task = platform.PushCore(e.Page, Element, e.Animated, e.Realize).ContinueWith((t, o) => true, null);
|
||||
}
|
||||
|
|
|
@ -397,7 +397,7 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
|
||||
void OnPopRequested(object sender, NavigationRequestedEventArgs e)
|
||||
{
|
||||
var newCurrent = (Page)PageController.InternalChildren[PageController.InternalChildren.Count - 2];
|
||||
var newCurrent = ((INavigationPageController)Element).Peek(1);
|
||||
SetPage(newCurrent, e.Animated, true);
|
||||
}
|
||||
|
||||
|
@ -418,8 +418,10 @@ namespace Xamarin.Forms.Platform.WinRT
|
|||
|
||||
void PushExistingNavigationStack()
|
||||
{
|
||||
for (int i = ((INavigationPageController)Element).StackCopy.Count - 1; i >= 0; i--)
|
||||
SetPage(((INavigationPageController)Element).StackCopy.ElementAt(i), false, false);
|
||||
foreach (var page in ((INavigationPageController)Element).Pages)
|
||||
{
|
||||
SetPage(page, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
void SetPage(Page page, bool isAnimated, bool isPopping)
|
||||
|
|
|
@ -211,7 +211,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
UpdateBarTextColor();
|
||||
|
||||
// If there is already stuff on the stack we need to push it
|
||||
((INavigationPageController)navPage).StackCopy.Reverse().ForEach(async p => await PushPageAsync(p, false));
|
||||
((INavigationPageController)navPage).Pages.ForEach(async p => await PushPageAsync(p, false));
|
||||
|
||||
_tracker = new VisualElementTracker(this);
|
||||
|
||||
|
@ -617,7 +617,7 @@ namespace Xamarin.Forms.Platform.iOS
|
|||
if (containerController == null)
|
||||
return;
|
||||
var currentChild = containerController.Child;
|
||||
var firstPage = ((INavigationPageController)Element).StackCopy.LastOrDefault();
|
||||
var firstPage = ((INavigationPageController)Element).Pages.FirstOrDefault();
|
||||
if ((firstPage != pageBeingRemoved && currentChild != firstPage && NavigationPage.GetHasBackButton(currentChild)) || _parentMasterDetailPage == null)
|
||||
return;
|
||||
|
||||
|
|
|
@ -26,6 +26,42 @@
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Pages">
|
||||
<MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerable<Xamarin.Forms.Page> Pages { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IEnumerable`1<class Xamarin.Forms.Page> Pages" />
|
||||
<MemberType>Property</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.Collections.Generic.IEnumerable<Xamarin.Forms.Page></ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>To be added.</summary>
|
||||
<value>To be added.</value>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Peek">
|
||||
<MemberSignature Language="C#" Value="public Xamarin.Forms.Page Peek (int depth);" />
|
||||
<MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class Xamarin.Forms.Page Peek(int32 depth) cil managed" />
|
||||
<MemberType>Method</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>Xamarin.Forms.Page</ReturnType>
|
||||
</ReturnValue>
|
||||
<Parameters>
|
||||
<Parameter Name="depth" Type="System.Int32" />
|
||||
</Parameters>
|
||||
<Docs>
|
||||
<param name="depth">To be added.</param>
|
||||
<summary>To be added.</summary>
|
||||
<returns>To be added.</returns>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="PopAsyncInner">
|
||||
<MemberSignature Language="C#" Value="public System.Threading.Tasks.Task<Xamarin.Forms.Page> PopAsyncInner (bool animated, bool fast = false);" />
|
||||
<MemberSignature Language="ILAsm" Value=".method public hidebysig newslot virtual instance class System.Threading.Tasks.Task`1<class Xamarin.Forms.Page> PopAsyncInner(bool animated, bool fast) cil managed" />
|
||||
|
@ -108,22 +144,6 @@
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="StackCopy">
|
||||
<MemberSignature Language="C#" Value="public System.Collections.Generic.Stack<Xamarin.Forms.Page> StackCopy { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.Stack`1<class Xamarin.Forms.Page> StackCopy" />
|
||||
<MemberType>Property</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.Collections.Generic.Stack<Xamarin.Forms.Page></ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>For internal use by platform renderers.</summary>
|
||||
<value>To be added.</value>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="StackDepth">
|
||||
<MemberSignature Language="C#" Value="public int StackDepth { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance int32 StackDepth" />
|
||||
|
|
|
@ -450,7 +450,7 @@
|
|||
<AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PopAsync>d__38))</AttributeName>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PopAsync>d__39))</AttributeName>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
<ReturnValue>
|
||||
|
@ -548,7 +548,7 @@
|
|||
<AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PopToRootAsync>d__46))</AttributeName>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PopToRootAsync>d__47))</AttributeName>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
<ReturnValue>
|
||||
|
@ -605,7 +605,7 @@
|
|||
<AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PushAsync>d__48))</AttributeName>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<PushAsync>d__49))</AttributeName>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
<ReturnValue>
|
||||
|
@ -844,6 +844,42 @@ public class MyPage : NavigationPage
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Xamarin.Forms.INavigationPageController.Pages">
|
||||
<MemberSignature Language="C#" Value="System.Collections.Generic.IEnumerable<Xamarin.Forms.Page> Xamarin.Forms.INavigationPageController.Pages { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IEnumerable`1<class Xamarin.Forms.Page> Xamarin.Forms.INavigationPageController.Pages" />
|
||||
<MemberType>Property</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.Collections.Generic.IEnumerable<Xamarin.Forms.Page></ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>To be added.</summary>
|
||||
<value>To be added.</value>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Xamarin.Forms.INavigationPageController.Peek">
|
||||
<MemberSignature Language="C#" Value="Xamarin.Forms.Page INavigationPageController.Peek (int depth);" />
|
||||
<MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class Xamarin.Forms.Page Xamarin.Forms.INavigationPageController.Peek(int32 depth) cil managed" />
|
||||
<MemberType>Method</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>Xamarin.Forms.Page</ReturnType>
|
||||
</ReturnValue>
|
||||
<Parameters>
|
||||
<Parameter Name="depth" Type="System.Int32" />
|
||||
</Parameters>
|
||||
<Docs>
|
||||
<param name="depth">To be added.</param>
|
||||
<summary>To be added.</summary>
|
||||
<returns>To be added.</returns>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Xamarin.Forms.INavigationPageController.PopAsyncInner">
|
||||
<MemberSignature Language="C#" Value="System.Threading.Tasks.Task<Xamarin.Forms.Page> INavigationPageController.PopAsyncInner (bool animated, bool fast);" />
|
||||
<MemberSignature Language="ILAsm" Value=".method hidebysig newslot virtual instance class System.Threading.Tasks.Task`1<class Xamarin.Forms.Page> Xamarin.Forms.INavigationPageController.PopAsyncInner(bool animated, bool fast) cil managed" />
|
||||
|
@ -856,7 +892,7 @@ public class MyPage : NavigationPage
|
|||
<AttributeName>System.Diagnostics.DebuggerStepThrough</AttributeName>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<Xamarin-Forms-INavigationPageController-PopAsyncInner>d__63))</AttributeName>
|
||||
<AttributeName>System.Runtime.CompilerServices.AsyncStateMachine(typeof(Xamarin.Forms.NavigationPage/<Xamarin-Forms-INavigationPageController-PopAsyncInner>d__64))</AttributeName>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
<ReturnValue>
|
||||
|
@ -874,22 +910,6 @@ public class MyPage : NavigationPage
|
|||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Xamarin.Forms.INavigationPageController.StackCopy">
|
||||
<MemberSignature Language="C#" Value="System.Collections.Generic.Stack<Xamarin.Forms.Page> Xamarin.Forms.INavigationPageController.StackCopy { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.Stack`1<class Xamarin.Forms.Page> Xamarin.Forms.INavigationPageController.StackCopy" />
|
||||
<MemberType>Property</MemberType>
|
||||
<AssemblyInfo>
|
||||
<AssemblyVersion>2.0.0.0</AssemblyVersion>
|
||||
</AssemblyInfo>
|
||||
<ReturnValue>
|
||||
<ReturnType>System.Collections.Generic.Stack<Xamarin.Forms.Page></ReturnType>
|
||||
</ReturnValue>
|
||||
<Docs>
|
||||
<summary>Internal</summary>
|
||||
<value>To be added.</value>
|
||||
<remarks>To be added.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
<Member MemberName="Xamarin.Forms.INavigationPageController.StackDepth">
|
||||
<MemberSignature Language="C#" Value="int Xamarin.Forms.INavigationPageController.StackDepth { get; }" />
|
||||
<MemberSignature Language="ILAsm" Value=".property instance int32 Xamarin.Forms.INavigationPageController.StackDepth" />
|
||||
|
|
Загрузка…
Ссылка в новой задаче