diff --git a/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt b/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt index 1d91ff0b8c3b0..8162b45a7f9fd 100644 --- a/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt +++ b/navigation/navigation-common/src/main/java/androidx/navigation/NavigatorProvider.kt @@ -103,6 +103,9 @@ public open class NavigatorProvider { ): Navigator? { require(validateName(name)) { "navigator name cannot be an empty string" } val previousNavigator = _navigators[name] + if (previousNavigator == navigator) { + return navigator + } check(previousNavigator?.isAttached != true) { "Navigator $navigator is replacing an already attached $previousNavigator" } diff --git a/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt b/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt index d4dcfe643d14d..8a6c0c691f044 100644 --- a/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt +++ b/navigation/navigation-common/src/test/java/androidx/navigation/NavigatorProviderTest.kt @@ -17,6 +17,7 @@ package androidx.navigation import android.os.Bundle +import androidx.navigation.testing.TestNavigatorState import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.junit.Assert.fail @@ -100,6 +101,50 @@ class NavigatorProviderTest { .isEqualTo(navigator) } + @Test + fun addExistingNavigatorDoesntReplace() { + val navigatorState = TestNavigatorState() + val provider = NavigatorProvider() + val navigator = EmptyNavigator() + + provider.addNavigator(navigator) + assertThat(provider.getNavigator(EmptyNavigator.NAME)) + .isEqualTo(navigator) + + navigator.onAttach(navigatorState) + assertWithMessage("Navigator should be attached") + .that(provider.getNavigator(EmptyNavigator.NAME).isAttached) + .isTrue() + + // addNavigator should throw when trying to replace an existing, attached navigator, but + // we should have returned before that + try { + provider.addNavigator(navigator) + } catch (navigatorAlreadyAttached: IllegalStateException) { + fail( + "addNavigator with an existing navigator should return early and not " + + "attempt to replace" + ) + } + } + + @Test + fun addWithSameNameButUnequalNavigatorDoesReplace() { + val provider = NavigatorProvider() + val navigatorA = EmptyNavigator() + val navigatorB = EmptyNavigator() + + assertThat(navigatorA).isNotEqualTo(navigatorB) + + provider.addNavigator(navigatorA) + assertThat(provider.getNavigator(EmptyNavigator.NAME)) + .isEqualTo(navigatorA) + + provider.addNavigator(navigatorB) + assertThat(provider.getNavigator(EmptyNavigator.NAME)) + .isEqualTo(navigatorB) + } + private val provider = NavigatorProvider() @Test