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

我遇到了 Dagger/MissingBinding 的问题。我在stackoverflow上把所有相关的答案都涂红了,我尝试使用不同的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 就可以了!谢谢!请将此作为答案发布以使其成为解决方案。

标签: android kotlin dagger-2 kapt


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-04
    • 2019-11-06
    • 2021-05-05
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多