Dagger-Hilt引发循环依赖问题求助(多模块MVVM Clean架构)
多模块MVVM Clean架构下Data与Domain模块循环依赖问题排查
错误日志
- What went wrong:
Circular dependency between the following tasks:
:AppLockFeature:data:compileDebugAidl
--- :AppLockFeature:domain:compileDebugAidl
--- :AppLockFeature:data:compileDebugAidl (*)
我采用多模块MVVM Clean架构,刚接触Dagger-Hilt,现在Data和Domain模块出现上述循环依赖错误,找不到问题原因,附上相关代码,求帮忙解决。
相关代码
Domain模块代码
AppLockRepo接口
interface AppLockRepo { fun getInstalledApps(): Flow<List<ApplicationInfo>> }
AppLockDomainModule模块
@Module @InstallIn(ViewModelComponent::class) object AppLockDomainModule { @ViewModelScoped // 注:@Singleton和@ViewModelScoped不能同时使用,这里保留@ViewModelScoped即可 fun provideUseCases(repo: AppLockRepo): AppLockUseCases { return AppLockUseCases( GetInstalledApps(repo) ) } }
GetInstalledApps用例
class GetInstalledApps( val repo: AppLockRepo ) { operator fun invoke(): Flow<List<ApplicationInfo>>{ return repo.getInstalledApps() } }
AppLockUseCases数据类
data class AppLockUseCases( val getInstalledApps: GetInstalledApps )
Data模块代码
AppLockRepoImpl实现类
class AppLockRepoImpl(val packageManager: PackageManager): AppLockRepo { override fun getInstalledApps(): Flow<List<ApplicationInfo>> { return flow { // 修正:需要emit数据,否则flow不会发射内容 emit(packageManager.getInstalledApplications(0)) } } }
AppLockDataModule模块
@Module @InstallIn(SingletonComponent::class) object AppLockDataModule { @Provides fun provideAppList(app: Application): PackageManager { return app.packageManager } @Provides fun provideAppLockRepo(packageManager: PackageManager): AppLockRepo { return AppLockRepoImpl(packageManager) } }
问题原因及解决方案
核心问题:模块依赖关系搞反
Clean架构的依赖规则是:Domain层是核心,不依赖任何外层模块;Data层作为实现层,必须依赖Domain层。你现在出现循环依赖,肯定是Gradle配置里让Domain模块依赖了Data模块,同时Data模块又依赖了Domain模块,导致编译任务互相调用形成闭环。
解决步骤
修正Gradle模块依赖
- 打开Domain模块的
build.gradle,删除所有对Data模块的依赖 - 打开Data模块的
build.gradle,添加对Domain模块的依赖(示例:implementation project(":AppLockFeature:domain"))
- 打开Domain模块的
修复Hilt注解冲突
- Domain模块的
AppLockDomainModule中,@Singleton和@ViewModelScoped不能同时使用,这里UseCases是给ViewModel提供的,保留@ViewModelScoped即可
- Domain模块的
修复Flow数据发射问题
- Data层的
AppLockRepoImpl中,flow里必须调用emit()发射数据,否则调用方拿不到结果
- Data层的
内容的提问来源于stack exchange,提问作者Vikas Gangishetty
相关产品推荐
相关产品推荐

