错误:[Dagger/MissingBinding] Map<Class<?扩展 ViewModel>, Provider<ViewModel>> 不能在没有 @P

Posted

技术标签:

【中文标题】错误:[Dagger/MissingBinding] Map<Class<?扩展 ViewModel>, Provider<ViewModel>> 不能在没有 @Provides-annotated 方法的情况下提供【英文标题】:error: [Dagger/MissingBinding] Map<Class<? extends ViewModel>, Provider<ViewModel>> cannot be provided without an @Provides-annotated method 【发布时间】:2020-06-06 17:55:41 【问题描述】:

我遇到了 Dagger/MissingBinding 的问题。我在***上把所有相关的答案都涂红了,我尝试使用不同的kotlin、gradle、dagger版本,我尝试使用不同的解决方法,例如kapt correctErrorTypes = true kapt generateStubs = true ,但问题仍然存在。

错误看起来像:

E:\androidStudioPrjcts\windygo\app\src\main\java\app\windygo\dagger\AppComponent.java:12: error: [Dagger/MissingBinding] java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> cannot be provided without an @Provides-annotated method.
public interface AppComponent 
       ^
      java.util.Map<java.lang.Class<? extends androidx.lifecycle.ViewModel>,javax.inject.Provider<androidx.lifecycle.ViewModel>> is injected at
          app.windygo.ui.DefaultViewModelFactory(creators)
      app.windygo.ui.DefaultViewModelFactory is injected at
          app.windygo.dagger.ViewModelModule.bindDefaultViewModelFactory(factory)
      androidx.lifecycle.ViewModelProvider.Factory is injected at
          app.windygo.dagger.DaggerWrapper.factory
      app.windygo.dagger.DaggerWrapper is injected at
          app.windygo.dagger.AppComponent.inject(app.windygo.dagger.DaggerWrapper)

还有我的消息来源:

AppComponent.java

package app.windygo.dagger;

import android.content.Context;

import javax.inject.Singleton;

import dagger.BindsInstance;
import dagger.Component;

@Singleton
@Component(modules =  AppModule.class, ViewModelModule.class )
public interface AppComponent 

    @Component.Builder
    interface Builder 
        @BindsInstance Builder context(Context context);
        AppComponent build();
    

    void inject(DaggerWrapper wrapper);

AppModule.java

package app.windygo.dagger;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import javax.inject.Singleton;

import app.windygo.BuildConfig;
import app.windygo.api.LiveDataCallAdapterFactory;
import app.windygo.api.WindyGoSource;
import dagger.Module;
import dagger.Provides;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

@Module
public class AppModule 
    @Singleton
    @Provides
    HttpLoggingInterceptor getInterceptor() 
        return new HttpLoggingInterceptor(/*new ApiLogger()*/);
    

    @Singleton
    @Provides
    HttpLoggingInterceptor.Level getLogLevel() 
        return BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE;
    

    @Singleton
    @Provides
    WindyGoSource provideGoodwineService() 
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.addInterceptor(chain -> 
            Request original = chain.request();

            String token = original.header(WindyGoSource.HEADER_AUTHORIZATION);
            if (token != null) 
                Request.Builder requestBuilder = original.newBuilder()
                        .header("Authorization", "Bearer " + token);

                original = requestBuilder.build();
            
            return chain.proceed(original);
        );
        builder.addNetworkInterceptor(getInterceptor().setLevel(getLogLevel()));
        OkHttpClient client = builder.build();

        Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();

        return new Retrofit.Builder()
                .baseUrl(BuildConfig.API_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(new LiveDataCallAdapterFactory())
                .client(client)
                .build()
                .create(WindyGoSource.class);
    


DaggerWrapper.java

package app.windygo.dagger;

import androidx.lifecycle.ViewModelProvider;

import javax.inject.Inject;

public class DaggerWrapper 

    @Inject
    ViewModelProvider.Factory factory;

    public ViewModelProvider.Factory getViewModelFactory() 
        return factory;
    

ViewModelKey.java

package app.windygo.dagger;

import androidx.lifecycle.ViewModel;

import dagger.MapKey;

@MapKey
@interface ViewModelKey 
    Class<? extends ViewModel> value();

ViewModelModule.java

package app.windygo.dagger;

import androidx.lifecycle.ViewModelProvider;

import app.windygo.ui.DefaultViewModelFactory;
import dagger.Binds;
import dagger.Module;

@Module
public abstract class ViewModelModule 

    @Binds
    public abstract ViewModelProvider.Factory bindDefaultViewModelFactory(DefaultViewModelFactory factory);


DefaultViewModelFactory.java

package app.windygo.ui;

import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.annotation.NonNull;

import java.util.Map;

import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;

@Singleton
public class DefaultViewModelFactory implements ViewModelProvider.Factory 

    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

    @Inject
    public DefaultViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) 
        this.creators = creators;
    

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) 
        Provider<? extends ViewModel> creator = creators.get(modelClass);
        if (creator == null) 
            throw new IllegalArgumentException("unknown model class " + modelClass);
        

        try 
            return (T) creator.get();
         catch (Exception e) 
            throw new RuntimeException(e);
        
    

由于在配置 Dagger 2 时 kapt 和 kotlin 存在不同的问题,我将 java 用于依赖于 dagger 的类。但我什至尝试使用 Kotlin 重写这些类,但它没有解决我的问题。

最后,我的 build.gradle 文件:

build.gradle(项目)

buildscript 
    ext.kotlin_version = '1.3.61'

    repositories 
        google()
        jcenter()

    
    dependencies 
        classpath 'com.android.tools.build:gradle:3.5.3'
        classpath 'com.google.gms:google-services:4.3.3'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
    


allprojects 
    repositories 
        google()
        jcenter()
        maven  url 'https://jitpack.io' 
    


task clean(type: Delete) 
    delete rootProject.buildDir

build.gradle(应用程序)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

def versionMajor = 1
def versionMinor = 0 // 0..9
def versionPatch = 0 // 0..9
def versionBuild = 0 // 0..99

static def getGitRevParseInfo(what) 
    def cmd = "git rev-parse " + what + " HEAD"
    def proc = cmd.execute()
    proc.text.trim()


android 
    compileSdkVersion 29
    defaultConfig 
        multiDexEnabled true
        applicationId "app.windygo"
        minSdkVersion 23
        targetSdkVersion 29
        versionCode versionMajor * 10000 + versionMinor * 1000 + versionPatch * 100 + versionBuild
        versionName "$versionMajor.$versionMinor.$versionPatch.$versionBuild"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    
    buildTypes 
        release 
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        
        debug 
            debuggable true
        
    
    compileOptions 
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    


dependencies 
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.13'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    // Dagger 2
    kapt "com.google.dagger:dagger-compiler:2.26"
    implementation "com.google.dagger:dagger:2.26"
    //Retrofit
    implementation 'com.squareup.retrofit2:retrofit:2.7.1'
    implementation 'com.squareup.retrofit2:converter-gson:2.7.1'
    implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'
    // ViewModel and LiveData
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.lifecycle:lifecycle-common-java8:2.2.0'

那么,请告诉我如何解决它?

【问题讨论】:

DefaultViewModelFactory中删除@Singleton @DrawnRaccoon,好的,我删除了这个注释,但没有帮助。 你也没有绑定任何ViewModelViewModelKey (@Binds @IntoMap @ViewModelKey(SomeViewModel.class) public abstract ViewModel bindSomeViewModel(SomeViewModel viewModel);) 是的,我没有。因为我还没有任何 ViewModel-s。我刚开始配置我的项目。好的,我会尝试创建一个。 @DrawnRaccoon 你是对的,绑定至少一个 ViewModel 就可以了!谢谢!请将此作为答案发布以使其成为解决方案。 【参考方案1】:

如果没有将至少一个ViewModelViewModelKey 绑定,dagger 不会创建提供Map&lt;Class&lt;? extends ViewModel&gt;, Provider&lt;ViewModel&gt;&gt; 的函数

【讨论】:

以上是关于错误:[Dagger/MissingBinding] Map<Class<?扩展 ViewModel>, Provider<ViewModel>> 不能在没有 @P的主要内容,如果未能解决你的问题,请参考以下文章

将依赖项注入ViewModel时的Dagger / MissingBinding

Dagger/MissingBinding java.util.Map<java.lang.Class<? extends ViewModel>,Provider<ViewMo

更新到 Kotlin 1.3.30 会破坏 Dagger 2.21 的构建

如何使用 Hilt 在存储库中注入应用程序上下文?

远程服务器返回错误: 404错误远程服务器返回错误:500错误 HttpWebResponse远程服务器返回错误:(404500) 错误。

Pig 安装错误:错误 pig.Main:错误 2998:未处理的内部错误