Repository navigation
Load the graph for a nested NavigatorHost that replaces another instance - #220
Merged
Merged
Conversation
Since #202, a NavigatorHost loads its graph in HotwireActivityDelegate.registerNavigatorHost(), which skips any host whose view ID is already registered. A fragment that hosts a nested NavigatorHost can be replaced by a new instance of itself, and the new nested host registers before the old one is destroyed. The new host never loads its graph, and when the old host unregisters it removes the ID entirely. The next route() on the new host's navigator throws "You must call setGraph() before calling getGraph()". A new host instance now takes over the ID, and a host only removes the entry while it still owns it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A fragment that hosts a nested
NavigatorHostcrashes when a new instance of the fragment replaces the old one before the old one is destroyed. This happens when a user leaves such a screen and quickly opens it again, for example while the old fragment's exit transition is still running.route()on the new host's navigator throws:Cause
#202 moved graph loading from
NavigatorHost.onCreate()intoHotwireActivityDelegate.registerNavigatorHost(). Registration is keyed by the host's view ID and skips any ID that's already registered. When the fragment gets replaced:onViewCreated()registers it. The old host still owns the ID, so the delegate skips the new host and it never loads its graph.onDestroy()unregisters it, which removes the ID entirely.route()on the new host's navigator readsNavController.graphand throws.Before #202,
onCreate()always loaded the graph, so step 1 didn't break anything.Fix
registerNavigatorHost()lets a new host instance take over an ID. The same instance still can't register twice, so a recreated view doesn't add a second destination listener.unregisterNavigatorHost()only removes the entry while the host still owns it.The old host keeps its destination listener. That listener only fires for the old host's own
NavController, which is on its way out.Tests
HotwireActivityDelegateTestadds 2 instances of a fragment with a nestedNavigatorHostunder the same ID, the second one before the first is removed:Both tests fail on
mainand pass with the fix. Reverting either half of the fix fails at least 1 of them../gradlew testReleasepasses.I also ran the repro in an app with a nested
NavigatorHoston an emulator, with the animator duration scale at 10x to keep the old fragment alive long enough. With 1.3.1, both runs crashed. With this branch, 3 runs didn't crash, and the nested navigator loaded and navigated normally.