Skip to content
This repository has been archived by the owner on May 1, 2024. It is now read-only.

Fix NRE if user immediately completes Deferral #13202

Merged
merged 5 commits into from
Dec 23, 2020
Merged

Fix NRE if user immediately completes Deferral #13202

merged 5 commits into from
Dec 23, 2020

Conversation

PureWeen
Copy link
Contributor

Description of Change

The deferral code was naively assuming there would be a delay between GetDeferral and Complete so the DeferralTask was never getting created.

  • Moved all of the shell navigation code into a specific ShellNavigationManager class so it's easier to follow
  • Streamlined the Deferral flow so the execution flow is more linear

Issues Resolved

Platforms Affected

  • Core/XAML (all platforms)

Testing Procedure

  • unit test included

PR Checklist

  • Targets the correct branch
  • Tests are passing (or failures are unrelated)

Made the deferral flow more linear and easy to follow
Moved the navigation parts of Shell out to a separate class
@PureWeen PureWeen added a/shell 🐚 blocker Issue blocks next stable release. Prioritize fixing and reviewing this issue. labels Dec 19, 2020
@PureWeen PureWeen added this to the 5.0.0 milestone Dec 19, 2020
@PureWeen PureWeen added this to To do in vNext+1 (5.0.0) via automation Dec 19, 2020

public ShellNavigatingEventArgs(ShellNavigationState current, ShellNavigationState target, ShellNavigationSource source, bool canCancel)
{

#if NETSTANDARD2_0
_deferralFinishedTask = () => Task.CompletedTask;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main fix. Just initializing the deferral finished task to a completed task so if no delayed task gets registered the code doesn't crash with an NRE


namespace Xamarin.Forms
{
internal class ShellNavigationManager
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is mainly a copy paste of the code that was already inside Shell


bool accept = !navigatingArgs.NavigationDelayedOrCancelled;
if (navigatingArgs.DeferredTask != null)
accept = await navigatingArgs.DeferredTask;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before this PR a deferred GotoAsync would always call GotoAsync again once the operation was completed but with these changes the same GotoAsync just continues on after the user has completed the deferral


Func<Task> navigationTask = () => GoToAsync(navArgs.Target, navArgs.Animate, false, navArgs);

if (Device.IsInvokeRequired)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the user completes the deferral off the UI Thread

@PureWeen PureWeen removed the request for review from StephaneDelcroix December 19, 2020 18:01
@rmarinho rmarinho moved this from To do to In Review in vNext+1 (5.0.0) Dec 19, 2020
Copy link
Contributor

@pictos pictos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't reproduce the NRE anymore

@PureWeen
Copy link
Contributor Author

Test failures unrelated

@rmarinho rmarinho merged commit cb1b8a3 into 5.0.0 Dec 23, 2020
vNext+1 (5.0.0) automation moved this from In Review to Done Dec 23, 2020
@rmarinho rmarinho deleted the fix_13131 branch December 23, 2020 12:12
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
a/navigation a/shell 🐚 blocker Issue blocks next stable release. Prioritize fixing and reviewing this issue. t/bug 🐛
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

[Bug] Shell Deferral is null during a navigation
4 participants