Designing Modular Apps - Circular Dependency problem in navigation

Here is my solution for stiuation. This enables the use of explicit intents. You can also apply this approach to single activity application with navigation component with a little modification.

Here is navigation object for module B

object ModuleBNavigator {

    internal lateinit var navigationImpl: ModuleBContract

    fun setNavigationImpl(navigationImpl: ModuleBContract) {
        this.navigationImpl = navigationImpl
    }

    interface ModuleBContract {
        fun navigateModuleA(self: Activity, bundle: Bundle?)
    }
}

And here is module B Activity

class ModuleBActivity : Activity() {

    companion object {
        private const val BUNDLE = "BUNDLE"
        fun newIntent(context: Context, bundle: Bundle?) = Intent(context, ModuleBActivity::class.java).apply {
            putExtra(BUNDLE, bundle)
        }
    }
}

And here is app module class to inject navigation impl to module A navigation object

class ApplicationModuleApp : Application() {

    // Can also inject with a DI library
    override fun onCreate() {
        super.onCreate()
        ModuleBNavigator.setNavigationImpl(object : ModuleBNavigator.ModuleBContract {
            override fun navigateModuleA(self: Activity, bundle: Bundle?) {
                self.startActivity(ModuleBActivity.newIntent(self, bundle))
            }
        })
    }
}

And finally you can navigate from module A -> module B with provided implementation

class ModuleAActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ... Some code 
        ModuleBNavigator.navigationImpl.navigateModuleA(this, Bundle())
        // .. Some code
    }
}

This approact avoids circler dependency and you don't have to use implicit intents anymore. Hope this helps.

Tags:

Android