Skip to content

Commit bce551e

Browse files
jossiwolfcopybara-github
authored andcommitted
[GH] [Navigation] Return early from NavigatorProvider#addNavigator if possible
We want to return early from `addNavigator` if the previous and to-be-added navigator are equal. This allows calling `addNavigator` as a side effect of every composition without having to worry about the Navigator being replaced every time. Test: Added addExistingNavigatorDoesntReplace and addWithSameNameButUnequalNavigatorDoesReplace in NavigatorProviderTest.kt Fixes: b/187443146 Change-Id: Id09b7e3306c49f261b80c724d36c614671f5a7ac This is an imported pull request from androidx#176. Resolves JetBrains#176 Github-Pr-Head-Sha: ba934c5 GitOrigin-RevId: 471dbf4 Change-Id: I5aefe997aaaf41f5080895c9c8cfcd6c83282eea
1 parent 4a1ec82 commit bce551e

2 files changed

Lines changed: 48 additions & 0 deletions

File tree

‎navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ public open class NavigatorProvider {
103103
): Navigator<out NavDestination>? {
104104
require(validateName(name)) { "navigator name cannot be an empty string" }
105105
val previousNavigator = _navigators[name]
106+
if (previousNavigator == navigator) {
107+
return navigator
108+
}
106109
check(previousNavigator?.isAttached != true) {
107110
"Navigator $navigator is replacing an already attached $previousNavigator"
108111
}

‎navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package androidx.navigation
1818

1919
import android.os.Bundle
20+
import androidx.navigation.testing.TestNavigatorState
2021
import com.google.common.truth.Truth.assertThat
2122
import com.google.common.truth.Truth.assertWithMessage
2223
import org.junit.Assert.fail
@@ -100,6 +101,50 @@ class NavigatorProviderTest {
100101
.isEqualTo(navigator)
101102
}
102103

104+
@Test
105+
fun addExistingNavigatorDoesntReplace() {
106+
val navigatorState = TestNavigatorState()
107+
val provider = NavigatorProvider()
108+
val navigator = EmptyNavigator()
109+
110+
provider.addNavigator(navigator)
111+
assertThat(provider.getNavigator<EmptyNavigator>(EmptyNavigator.NAME))
112+
.isEqualTo(navigator)
113+
114+
navigator.onAttach(navigatorState)
115+
assertWithMessage("Navigator should be attached")
116+
.that(provider.getNavigator<EmptyNavigator>(EmptyNavigator.NAME).isAttached)
117+
.isTrue()
118+
119+
// addNavigator should throw when trying to replace an existing, attached navigator, but
120+
// we should have returned before that
121+
try {
122+
provider.addNavigator(navigator)
123+
} catch (navigatorAlreadyAttached: IllegalStateException) {
124+
fail(
125+
"addNavigator with an existing navigator should return early and not " +
126+
"attempt to replace"
127+
)
128+
}
129+
}
130+
131+
@Test
132+
fun addWithSameNameButUnequalNavigatorDoesReplace() {
133+
val provider = NavigatorProvider()
134+
val navigatorA = EmptyNavigator()
135+
val navigatorB = EmptyNavigator()
136+
137+
assertThat(navigatorA).isNotEqualTo(navigatorB)
138+
139+
provider.addNavigator(navigatorA)
140+
assertThat(provider.getNavigator<EmptyNavigator>(EmptyNavigator.NAME))
141+
.isEqualTo(navigatorA)
142+
143+
provider.addNavigator(navigatorB)
144+
assertThat(provider.getNavigator<EmptyNavigator>(EmptyNavigator.NAME))
145+
.isEqualTo(navigatorB)
146+
}
147+
103148
private val provider = NavigatorProvider()
104149

105150
@Test

0 commit comments

Comments
 (0)