如何摆脱 Hilt 的循环编译错误?
How can I get rid of cycle compile error from Hilt?
这是我的代码。
RemoteConfigRepository
class RemoteConfigRepository
@Inject constructor(
val service: RemoteConfigService): Repository {
suspend fun getConfig(): Response<RemoteConfigResponseBody>
= service.getConfig()
}
存储库模块
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(
repository: RemoteConfigRepository
): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
// ...
}
EntryViewModel
@HiltViewModel
class EntryViewModel
@Inject constructor(
private val repository: RemoteConfigRepository,
private val savedStateHandle: SavedStateHandle
): ViewModel() {
// ...
}
这是 EntryActivity
@AndroidEntryPoint
class EntryActivity : BaseActivity() {
lateinit var binding: ActivityEntryBinding
@VisibleForTesting
private val viewModel by viewModels<EntryViewModel>()
// ...
}
然后我得到
ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1/Users/user/Documents/Github/my_app/build/generated/source/kapt/debug/com/example/MyApplication_HiltComponents.java:152: error: [Dagger/DependencyCycle] Found a dependency cycle:
public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
^
com.example.repository.RemoteConfigRepository is injected at
com.example.di.RepositoryModule.provideRemoteConfigRepository(repository)
com.example.repository.RemoteConfigRepository is injected at
com.example.ui.entry.EntryViewModel(repository, …)
com.example.ui.entry.EntryViewModel is injected at
com.example.ui.entry.EntryViewModel_HiltModules.BindsModule.binds(vm)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.example.MyApplication_HiltComponents.SingletonC → com.example.MyApplication_HiltComponents.ActivityRetainedC → com.example.MyApplication_HiltComponents.ViewModelC][WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.room.RoomProcessor (DYNAMIC).
不知道循环从何而来..
您需要从 provideRemoteConfigRepository
中删除参数:
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
// ...
}
为什么您期望 RemoteConfigRepository
而您从该方法返回相同的结果。这导致了循环依赖。它应该是这样的。
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(
service: BaseService
): RemoteConfigRepository {
return RemoteConfigRepository(service)
}
@Provides
@ViewModelScoped
fun provideBaseService(): BaseService {
return BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java)
}
}
在这种情况下,您可以将 provideBaseService
标记为适当的范围,我认为它应该属于 Singleton
范围。
对于第二种方法,您可以这样做,默认情况下 BaseService
ViewModelScoped
.
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
}
这是我的代码。
RemoteConfigRepository
class RemoteConfigRepository
@Inject constructor(
val service: RemoteConfigService): Repository {
suspend fun getConfig(): Response<RemoteConfigResponseBody>
= service.getConfig()
}
存储库模块
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(
repository: RemoteConfigRepository
): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
// ...
}
EntryViewModel
@HiltViewModel
class EntryViewModel
@Inject constructor(
private val repository: RemoteConfigRepository,
private val savedStateHandle: SavedStateHandle
): ViewModel() {
// ...
}
这是 EntryActivity
@AndroidEntryPoint
class EntryActivity : BaseActivity() {
lateinit var binding: ActivityEntryBinding
@VisibleForTesting
private val viewModel by viewModels<EntryViewModel>()
// ...
}
然后我得到
ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1ANTLR Tool version 4.5.3 used for code generation does not match the current runtime version 4.7.1ANTLR Runtime version 4.5.3 used for parser compilation does not match the current runtime version 4.7.1/Users/user/Documents/Github/my_app/build/generated/source/kapt/debug/com/example/MyApplication_HiltComponents.java:152: error: [Dagger/DependencyCycle] Found a dependency cycle:
public abstract static class SingletonC implements HiltWrapper_ActivityRetainedComponentManager_ActivityRetainedComponentBuilderEntryPoint,
^
com.example.repository.RemoteConfigRepository is injected at
com.example.di.RepositoryModule.provideRemoteConfigRepository(repository)
com.example.repository.RemoteConfigRepository is injected at
com.example.ui.entry.EntryViewModel(repository, …)
com.example.ui.entry.EntryViewModel is injected at
com.example.ui.entry.EntryViewModel_HiltModules.BindsModule.binds(vm)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.example.MyApplication_HiltComponents.SingletonC → com.example.MyApplication_HiltComponents.ActivityRetainedC → com.example.MyApplication_HiltComponents.ViewModelC][WARN] Incremental annotation processing requested, but support is disabled because the following processors are not incremental: androidx.room.RoomProcessor (DYNAMIC).
不知道循环从何而来..
您需要从 provideRemoteConfigRepository
中删除参数:
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
// ...
}
为什么您期望 RemoteConfigRepository
而您从该方法返回相同的结果。这导致了循环依赖。它应该是这样的。
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(
service: BaseService
): RemoteConfigRepository {
return RemoteConfigRepository(service)
}
@Provides
@ViewModelScoped
fun provideBaseService(): BaseService {
return BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java)
}
}
在这种情况下,您可以将 provideBaseService
标记为适当的范围,我认为它应该属于 Singleton
范围。
对于第二种方法,您可以这样做,默认情况下 BaseService
ViewModelScoped
.
@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
@Provides
@ViewModelScoped
fun provideRemoteConfigRepository(): RemoteConfigRepository {
return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
}
}