注入ViewModel时Dagger MissingBinding错误

问题描述 投票:0回答:1

我在重建项目时遇到了匕首注入的问题。我最近开始学习 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()
            }
        }
    }
}

我尝试用谷歌搜索它,但没有任何效果

android mvvm dagger-2
1个回答
0
投票

您的错误表明您正在尝试使用一些未提供给依赖关系图的对象。

  1. 如果没有 @Inject 构造函数或 @Provides 注释方法,则无法提供 com.example.weatherforecast_rxjava_mvvm_dagger2.data.api.interceptors.LoggingInterceptor。

在您的 AppModule 中,您需要提供 LoggingInterceptor 的实例以使用它来创建 HttpLoggingInterceptor。在provideLoggingInterceptor之后添加这个功能

@Provides
@Singleton
fun provideLoggingInterceptorImpl(): LoggingInterceptor {
    // return LoggingInterceptor()
}

或者从provideLoggingInterceptor函数中删除loggingInterceptor参数。

  1. 如果没有 @Inject 构造函数或 @Provides 注释方法,则无法提供 android.app.Application。

看起来您的 LocationTrackerImpl 已注入应用程序。将这些行添加到您的 AppComponent 中并使用生成器创建它,为图表提供应用程序:

@Component.Builder
interface Builder {

    fun build(): AppComponent

    @BindsInstance
    fun app(app: Application): Builder
}

然后,AppComponent 的创建位置:

val appComponent = DaggerAppComponent.builder().app(this).build()
© www.soinside.com 2019 - 2024. All rights reserved.