如何在Feature模块中访问App模块组件并实现反向导航?
跨模块反向导航解决方案
针对Feature模块无法依赖App模块导致的反向导航问题,以下是几种解耦且可行的实现方案:
方案一:接口回调解耦
在Feature模块定义导航接口,由App模块的组件实现该接口,通过接口回调触发反向导航。
- 在feature1Module中定义导航接口
// feature1Module/Feature1Navigator.kt interface Feature1Navigator { fun navigateBackToDashboard() }
- 在Feature1Fragment中持有接口引用并触发回调
class Feature1Fragment : Fragment() { private var navigator: Feature1Navigator? = null override fun onAttach(context: Context) { super.onAttach(context) // 从宿主Activity或父Fragment获取接口实现 navigator = when { context is Feature1Navigator -> context parentFragment is Feature1Navigator -> parentFragment as Feature1Navigator else -> null } } override fun onDetach() { super.onDetach() navigator = null } // 点击返回按钮时触发 private fun goBack() { navigator?.navigateBackToDashboard() } }
- 在App模块的DashboardFragment中实现接口
class DashboardFragment : Fragment(), Feature1Navigator { override fun navigateBackToDashboard() { // 执行返回逻辑,如返回栈弹出 findNavController().popBackStack() } }
方案二:Jetpack Navigation 深层链接
通过隐式深层链接导航,无需依赖App模块的具体组件类。
- 在App模块的导航图中配置DashboardFragment的深层链接
<!-- res/navigation/nav_graph.xml --> <fragment android:id="@+id/dashboardFragment" android:name="com.xxx.app.DashboardFragment"> <deepLink app:uri="app://your-app-domain/dashboard" /> </fragment>
- 在Manifest中为宿主Activity添加深层链接过滤
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="app" android:host="your-app-domain" /> </intent-filter> </activity>
- 在Feature1Fragment中触发深层链接导航
private fun navigateBackToDashboard() { // 使用Navigation组件直接导航 findNavController().navigate(Uri.parse("app://your-app-domain/dashboard")) // 或通过Intent跳转 // startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("app://your-app-domain/dashboard"))) }
方案三:事件总线传递导航事件
通过事件总线(如EventBus)发送导航事件,由App模块的组件订阅并处理。
- 在公共Core模块(所有模块依赖)定义导航事件
// coreModule/NavigationEvents.kt data class NavigateToDashboardEvent
- 在App模块的DashboardFragment中订阅事件
class DashboardFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) EventBus.getDefault().register(this) } override fun onDestroyView() { super.onDestroyView() EventBus.getDefault().unregister(this) } @Subscribe(threadMode = ThreadMode.MAIN) fun handleNavigateEvent(event: NavigateToDashboardEvent) { findNavController().popBackStack() } }
- 在Feature1Fragment中发送导航事件
private fun goBackToDashboard() { EventBus.getDefault().post(NavigateToDashboardEvent()) }
注意:需给所有相关模块添加EventBus依赖:
implementation 'org.greenrobot:eventbus:3.3.1'
方案四:依赖注入(Hilt)统一管理导航
通过DI框架将App侧的导航逻辑注入到Feature模块,实现解耦。
- 在Core模块定义导航接口
// coreModule/AppNavigator.kt interface AppNavigator { fun navigateBackToDashboard(fragment: Fragment) }
- 在App模块实现导航接口并通过Hilt绑定
// appModule/AppNavigatorImpl.kt class AppNavigatorImpl @Inject constructor() : AppNavigator { override fun navigateBackToDashboard(fragment: Fragment) { fragment.findNavController().popBackStack() } } // appModule/Di/AppModule.kt @Module @InstallIn(SingletonComponent::class) object AppModule { @Provides fun provideAppNavigator(): AppNavigator = AppNavigatorImpl() }
- 在Feature1Fragment中注入导航接口并使用
@AndroidEntryPoint class Feature1Fragment : Fragment() { @Inject lateinit var appNavigator: AppNavigator private fun goBack() { appNavigator.navigateBackToDashboard(this) } }
方案选型建议
- 接口回调:适合小型项目或简单导航场景,无额外依赖,耦合度低
- 深层链接:适合跨模块/跨App的导航需求,配置简单
- 事件总线:适合复杂的跨模块事件传递,但需注意避免滥用导致维护成本上升
- 依赖注入:适合大型模块化项目,配合DI框架可统一管理导航逻辑,扩展性强
内容的提问来源于stack exchange,提问作者G Anil Reddy
相关产品推荐
相关产品推荐

