如何摆脱 Hilt 的循环编译错误?

时间:2021-03-23 09:25:31

标签: android dependency-injection dagger-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))
    }
    // ...

}

入口视图模型

@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).

我不知道循环从何而来..

2 个答案:

答案 0 :(得分:1)

为什么您期望 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))
}
}

答案 1 :(得分:0)

您需要从 provideRemoteConfigRepository 中删除参数:

@Module
@InstallIn(ViewModelComponent::class)
object RepositoryModule {
    @Provides
    @ViewModelScoped
    fun provideRemoteConfigRepository(): RemoteConfigRepository {
        return RemoteConfigRepository(BaseService(UrlConstants.REMOTE_CONFIG_BASE_URL).createApi(RemoteConfigService::class.java))
    }
    // ...

}