我刚刚重构了匕首代码,使其可扩展,并将所有核心内容移动到名为di的单独模块中。
现在,当我尝试将依赖项注入应用程序模块时,我得到了这个:
[Dagger/MissingBinding] retrofit2.Retrofit cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface ResetPasswordComponent {
^
retrofit2.Retrofit is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordNetworkModule.providerResetPasswordAPI(retrofit)
com.sahra.oms.ibshop.data.remote.service.ResetPasswordService is injected at
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueRepositoryImpl(resetPasswordService)
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueRepositoryImpl is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordModule.bindUniqueIdRepository(uniqueRepositoryImpl)
com.sahra.oms.ibshop.data.repisotory.nationalid.UniqueIdRepository is injected at
com.sahra.oms.ibshop.features.resetpassword.uniqueid.CheckUniqueIDViewModel(repository)
com.sahra.oms.ibshop.features.resetpassword.uniqueid.CheckUniqueIDViewModel is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordModule.bindCheckIdViewModel(checkUniqueIDViewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.sahra.oms.ibishop.di.util.ViewModelFactory(viewModelsMap)
com.sahra.oms.ibishop.di.util.ViewModelFactory is injected at
com.sahra.oms.ibshop.di.ViewModelBuilder.bindViewModelFactory(arg0)
androidx.lifecycle.ViewModelProvider.Factory is injected at
com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment.viewModelFactory
com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment is injected at
com.sahra.oms.ibshop.features.resetpassword.di.ResetPasswordComponent.inject(com.sahra.oms.ibshop.features.resetpassword.newpassword.NewPasswordFragment)
ResetPasswordService只是一个Retrofit接口。
这是我的代码:
AppComponent
@Singleton
@AppScope
@Component
interface AppComponent {
fun provideContextComponent(): ContextComponent
fun provideNetworkComponent(): NetworkComponent
fun provideSharedPrefComponent(): SharedPreferencesComponent
fun inject(app: Application)
@Component.Factory
interface Factory {
fun create(
@BindsInstance
context: ContextComponent,
@BindsInstance
network: NetworkComponent,
@BindsInstance
sharedPrefs: SharedPreferencesComponent
): AppComponent
}
}
NetworkComponent:
@Scope
@Retention(AnnotationRetention.RUNTIME)
annotation class NetworkScope
@NetworkScope
@Component(
dependencies = [ContextComponent::class],
modules = [OkHttpModule::class, AuthBinderModule::class]
)
interface NetworkComponent {
fun provideOkHttp(): OkHttpClient
fun provideRetrofit(): Retrofit
fun provideGson(): GsonConverterFactory
}
OkHttpModule:
@Module
object OkHttpModule {
private const val BASE_URL = "base_url"
@Provides
@JvmStatic
fun provideLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor(
HttpLoggingInterceptor.Logger { message -> Log.d("<<<network>>>", message) }).apply {
level = if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE
}
}
@Provides
@JvmStatic
fun provideChuckInterceptor(app: Application): ChuckInterceptor = ChuckInterceptor(app)
@Provides
@JvmStatic
fun provideOkhttpCache(app: Application): Cache =
Cache(app.cacheDir, 50_000_000)
@Provides
@NetworkScope
@JvmStatic
fun provideClient(
loggingInterceptor: HttpLoggingInterceptor,
chuckInterceptor: ChuckInterceptor,
authInterceptor: Interceptor,
cache: Cache
): OkHttpClient {
return OkHttpClient.Builder()
.cache(cache)
.addInterceptor(loggingInterceptor)
.addInterceptor(authInterceptor)
.addInterceptor(chuckInterceptor)
.build()
}
@Provides
@NetworkScope
@JvmStatic
fun provideGson() = Gson()
@Provides
@JvmStatic
fun provideGsonConverter(gson: Gson) = GsonConverterFactory.create(gson)
@Provides
@NetworkScope
@JvmStatic
fun provideRetrofit(
gsonConverterFactory: GsonConverterFactory,
client: Lazy<OkHttpClient>
): Retrofit = Retrofit.Builder()
.callFactory { request -> client.get().newCall(request) }
.baseUrl(BASE_URL)
.addConverterFactory(gsonConverterFactory)
.build()
}
这是我尝试注入依赖项的方式:
@FeatureScope
@Component(
dependencies = [AppComponent::class],
modules = [
ResetPasswordNetworkModule::class,
ResetPasswordModule::class,
ViewModelBuilder::class
]
)
interface ResetPasswordComponent {
fun inject(newPasswordFragment: NewPasswordFragment)
fun inject(checkUniqueIDFragment: CheckUniqueIDFragment)
@Component.Builder
interface Builder {
fun coreComponent(appComponent: AppComponent): Builder
fun build(): ResetPasswordComponent
}
}
@Module
abstract class ResetPasswordModule {
@Binds
abstract fun bindResetPasswordRepository(resetPasswordRepositoryImpl: ResetPasswordRepositoryImpl): ResetPasswordRepository
@Binds
abstract fun bindUniqueIdRepository(uniqueRepositoryImpl: UniqueRepositoryImpl): UniqueIdRepository
@Binds
@IntoMap
@ViewModelKey(CheckUniqueIDViewModel::class)
abstract fun bindCheckIdViewModel(checkUniqueIDViewModel: CheckUniqueIDViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(NewPasswordViewModel::class)
abstract fun bindNewPasswordViewModel(newPasswordViewModel: NewPasswordViewModel): ViewModel
}
@Module
object ResetPasswordNetworkModule {
@Provides
@JvmStatic
@FeatureScope
fun provideUserAPI(
retrofit: Retrofit
): ResetPasswordService = retrofit.create(ResetPasswordService::class.java)
}
这是我的存储库代码:
class ResetPasswordRepositoryImpl @Inject constructor(
private val resetPasswordService: ResetPasswordService
) : ResetPasswordRepository {
}
片段:
class NewPasswordFragment{
@Inject
lateinit var viewModelFactory: ViewModelProvider.Factory
}
class NewPasswordViewModel @Inject constructor(
private val repository: ResetPasswordRepository
)
提前感谢。
您的应用程序组件工厂看起来像这样:
fun create(
@BindsInstance
context: ContextComponent,
@BindsInstance
network: NetworkComponent,
@BindsInstance
sharedPrefs: SharedPreferencesComponent
): AppComponent
这提供对NetworkComponent
实例的访问,因此需要@Provides
的任何@Binds
,@Inject
或NetworkComponent
都可以得到一个。它确实not,但是可以直接访问NetworkComponent
的对象图。
NetworkComponent
已经公开了Retrofit
,因此如果可以访问该组件,则可以肯定获得一个。但是,此过程不是自动的,并且在您的设置中需要使用@Provides
方法。
@Provides
fun provideRetrofit(component: NetworkComponent): Retrofit = component.provideRetrofit()
这是需要解决的。一种更好的方法是使NetworkComponent
成为AppComponent
的依赖项(或仅使用其模块并完全删除网络组件),然后在Retrofit
中公开AppComponent
。
// using multiple scoped dependencies requires Dagger 2.27
@AppScope
@Component(dependencies = [ContextComponent::class, NetworkComponent::class, SharedPreferencesComponent::class])
interface AppComponent {
fun provideRetrofit(): Retrofit
// ...
}