我在重建项目时遇到了匕首注入的问题。我最近开始学习 dagger 2 ,遇到了这个错误,有人可以帮助我吗?我花了很多时间,你的回答对我有很大帮助。
[Dagger/MissingBinding] com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.interceptors.LoggingInterceptor cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface AppComponent {
^
Missing binding usage:
com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.interceptors.LoggingInterceptor is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideLoggingInterceptor(loggingInterceptor)
okhttp3.logging.HttpLoggingInterceptor is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideOkHttp(loggingInterceptor)
okhttp3.OkHttpClient is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideRetrofit(okHttp)
retrofit2.Retrofit.Builder is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideApi(builder)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.WeatherApi is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.data.repository.WeatherRepositoryImpl(weatherApi, �)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.repository.WeatherRepositoryImpl is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.RepositoryModule.bindRepository(repository)
com.example.weatherforecast_rxjava_mvvm_dagger2.domain.repository.WeatherRepository is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel(repository, �)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.ViewModelModule.bindViewModel(viewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory(creators)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory is requested at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.viewModelFactory()
The following other entry points also depend on it:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.inject(com.example.weatherforecast_rxjava_mvvm_dagger2.MainActivity)
[Dagger/MissingBinding] android.app.Application cannot be provided without an @Inject constructor or an @Provides-annotated method.
public abstract interface AppComponent {
^
Missing binding usage:
android.app.Application is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.data.location.LocationTrackerImpl(�, application)
com.example.weatherforecast_rxjava_mvvm_dagger2.data.location.LocationTrackerImpl is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.LocationModule.bindLocationTracker(locationTracker)
com.example.weatherforecast_rxjava_mvvm_dagger2.domain.location.LocationTracker is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel(�, locationTracker)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.WeatherViewModel is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.ViewModelModule.bindViewModel(viewModel)
java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory(creators)
com.example.weatherforecast_rxjava_mvvm_dagger2.ui.ViewModelFactory is requested at
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.viewModelFactory()
It is also requested at:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppModule.provideFusedLocationProviderClient(app)
The following other entry points also depend on it:
com.example.weatherforecast_rxjava_mvvm_dagger2.di.AppComponent.inject(com.example.weatherforecast_rxjava_mvvm_dagger2.MainActivity)
以下是我的课程:
应用组件
@Singleton
@Component(modules = [AppModule::class, LocationModule::class, RepositoryModule::class, ViewModelModule::class])
interface AppComponent {
fun inject(mainActivity: MainActivity)
fun viewModelFactory(): ViewModelFactory
}
应用模块
@Module
object AppModule {
@Provides
@Singleton
fun provideApi(builder: Retrofit.Builder): WeatherApi {
return builder
.build()
.create(WeatherApi::class.java)
}
@Provides
@Singleton
fun provideRetrofit(okHttp: OkHttpClient): Retrofit.Builder {
return Retrofit.Builder()
.baseUrl(ApiConstants.API_BASE_URL)
.client(okHttp)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
}
@Provides
@Singleton
fun provideOkHttp(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.build()
}
@Provides
@Singleton
fun provideLoggingInterceptor(loggingInterceptor: LoggingInterceptor): HttpLoggingInterceptor {
val httpLoggingInterceptor = HttpLoggingInterceptor(loggingInterceptor)
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
return httpLoggingInterceptor
}
@Provides
@Singleton
fun provideFusedLocationProviderClient(app: Application): FusedLocationProviderClient {
return LocationServices.getFusedLocationProviderClient(app)
}
}
位置模块
@Module
interface LocationModule {
@Binds
@Singleton
fun bindLocationTracker(locationTracker: LocationTrackerImpl): LocationTracker
}
存储库模块
@Module
interface RepositoryModule {
@Binds
@Singleton
fun bindRepository(repository: WeatherRepositoryImpl): WeatherRepository
}
ViewModelKey
@MustBeDocumented
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@MapKey
annotation class ViewModelKey(val value: KClass<out ViewModel>)
视图模型工厂
@Suppress("UNCHECKED_CAST")
@Singleton
class ViewModelFactory @Inject
constructor(
private val creators: Map<Class<out ViewModel>,
@JvmSuppressWildcards Provider<ViewModel>>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) {
for ((key, value) in creators) {
if (modelClass.isAssignableFrom(key)) {
creator = value
break
}
}
}
if (creator == null) {
throw IllegalArgumentException("unknown model class " + modelClass)
}
try {
return creator.get() as T
} catch (e: Exception) {
throw RuntimeException(e)
}
}
}
天气视图模型
class WeatherViewModel @Inject constructor(
private val repository: WeatherRepository,
private val locationTracker: LocationTracker
): ViewModel() {
private val disposables = CompositeDisposable()
private var _state = MutableStateFlow(WeatherState())
val state = _state.asStateFlow()
override fun onCleared() {
disposables.dispose()
super.onCleared()
}
init {
locationTracker.getCurrentLocation().subscribe(object : SingleObserver<Location?> {
override fun onSubscribe(d: Disposable) {
disposables.add(d)
}
override fun onError(e: Throwable) {
_state.value.weather = State.Error(e.message.orEmpty())
}
override fun onSuccess(location: Location) {
location.let {
repository.getWeatherData(it.latitude, it.longitude).subscribe(object : SingleObserver<State<Weather>> {
override fun onSubscribe(d: Disposable) {
disposables.add(d)
}
override fun onError(e: Throwable) {
_state.value.weather = State.Error(e.message.orEmpty())
}
override fun onSuccess(weatherState: State<Weather>) {
_state.value.weather = weatherState
}
})
}
}
})
}
}
天气应用程序
class WeatherApp: Application() {
lateinit var appComponent: AppComponent
override fun onCreate() {
super.onCreate()
appComponent = DaggerAppComponent.builder().build()
}
}
val Context.appComponent: AppComponent
get() = when (this) {
is WeatherApp -> appComponent
else -> this.applicationContext.appComponent
}
主要活动
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var permissionLauncher: ActivityResultLauncher<Array<String>>
@Inject
lateinit var viewModelFactory: ViewModelFactory
private lateinit var viewModel: WeatherViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
appComponent.inject(this)
permissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) {}
permissionLauncher.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
))
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
viewModel = ViewModelProvider(this, viewModelFactory)[WeatherViewModel::class.java]
when(val weatherState = viewModel.state.value.weather) {
is State.Loading -> {
TODO()
}
is State.Success -> {
TODO()
}
is State.Error -> {
TODO()
}
}
}
}
我尝试用谷歌搜索它,但没有任何效果
您的错误表明您正在尝试使用一些未提供给依赖关系图的对象。
在您的 AppModule 中,您需要提供 LoggingInterceptor 的实例以使用它来创建 HttpLoggingInterceptor。在provideLoggingInterceptor之后添加这个功能
@Provides
@Singleton
fun provideLoggingInterceptorImpl(): LoggingInterceptor {
// return LoggingInterceptor()
}
或者从provideLoggingInterceptor函数中删除loggingInterceptor参数。
看起来您的 LocationTrackerImpl 已注入应用程序。将这些行添加到您的 AppComponent 中并使用生成器创建它,为图表提供应用程序:
@Component.Builder
interface Builder {
fun build(): AppComponent
@BindsInstance
fun app(app: Application): Builder
}
然后,AppComponent 的创建位置:
val appComponent = DaggerAppComponent.builder().app(this).build()