Dolch: IllegalArgumentException: Keine Injektorfabrik für Klasse gebunden

Lesezeit: 6 Minuten

Benutzer-Avatar
dev_android

Ich bin neu bei Dagger 2. Ich habe 2 Aktivitäten, ich möchte injiziertes ViewModel für beide verwenden. Hier ist mein ViewModuleFactory :

@Singleton
public class ProductViewModelFactory implements ViewModelProvider.Factory {

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

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


    @SuppressWarnings("unchecked")
    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        Provider<? extends ViewModel> creator = creators.get(modelClass);
        if (creator == null) {
            for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
                if (modelClass.isAssignableFrom(entry.getKey())) {
                    creator = entry.getValue();
                    break;
                }
            }
        }
        if (creator == null) {
            throw new IllegalArgumentException("unknown viewmodel class " + modelClass);
        }
        try {
            return (T) creator.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Mein ViewModelModule:

@Module
abstract class ViewModelModule {
    @Binds
    @IntoMap
    @ViewModelKey(ProductListViewModel.class)
    abstract ViewModel bindProductListViewModel(ProductListViewModel listViewModel);

    @Binds
    @IntoMap
    @ViewModelKey(ProductDetailsViewModel.class)
    abstract ViewModel bindProductDetailsViewModel(ProductDetailsViewModel detailsViewModel);

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(ProductViewModelFactory factory);
}

Mein ViewModelKey zum Mapping:

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
    Class<? extends ViewModel> value();
}

Mein ActivityModul :

@Module
public abstract class ActivityModule {
    abstract ProductListActivity contributeProductListActivity();
    abstract ProductDetailsActivity contributeProductDetailsActivity();
}

Mein AppModul:

@Module
class AppModule {

@Provides
    @Singleton
    RedMartProductService provideRedMartProductService() {
        ........
    }

    @Provides
    @Singleton
    ProductListRepository provideProductListRepository(ProductListRepository repository) {
        return repository;
    }

    @Provides
    @Singleton
    ProductDetailsRepository provideProductDetailsRepository(ProductDetailsRepository repository) {
        return repository;
    }
}

Mein AppComponent:

@Singleton
@Component(modules = {AndroidInjectionModule.class, ActivityModule.class, AppModule.class})
public interface AppComponent {
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }

    void inject(MartApplication martApp);
}

Mein Anwendung:

public class MartApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
}

Im Aktivität:

@Inject
ViewModelProvider.Factory viewModelFactory;
.......
AndroidInjection.inject(activity); // Throwing exception
ListViewModel = ViewModelProviders.of(this, viewModelFactory).get(ProductListViewModel.class);

Es löst eine Ausnahme beim Inject aus:

java.lang.IllegalArgumentException: No injector factory bound for Class<com.mymart.ui.ProductListActivity>

Kann mir jemand helfen, das Problem in meinem Code zu identifizieren?

……………………………………………. ………………….

Bearbeiten: Ich habe versucht mit ContributesAndroidInjector gemäß @azizbekian, aber es führte zu folgendem Fehler beim Build:

    error: [dagger.android.AndroidInjector.inject(T)] Found a dependency cycle:
com.mymart.repository.ProductListRepository is injected at
com.mymart.di.AppModule.provideProductListRepository(repository)
com.mymart.repository.ProductListRepository is injected at
com.mymart.viewmodel.ProductListViewModel.<init>(productListRepository)
com.mymart.viewmodel.ProductListViewModel is injected at
com.mymart.di.ViewModelModule.bindProductListViewModel(listViewModel)
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.mymart.viewmodel.ProductViewModelFactory.<init>(creators)
com.mymart.viewmodel.ProductViewModelFactory is injected at
com.mymart.di.ViewModelModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.mymart.ui.ProductListActivity.viewModelFactory
com.mymart.ui.ProductListActivity is injected at
dagger.android.AndroidInjector.inject(arg0)

Bearbeiten 2
Nach allen Änderungen stehe ich wieder vor einer Ausnahme:

java.lang.RuntimeException: Unable to create application com.kaushik.myredmart.MartApplication: java.lang.IllegalStateException: com.kaushik.myredmart.di.AppModule must be set
                                                 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4710)
                                                 at android.app.ActivityThread.-wrap1(ActivityThread.java)
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405)
                                                 at android.os.Handler.dispatchMessage(Handler.java:102)
                                                 at android.os.Looper.loop(Looper.java:148)
                                                 at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                 at java.lang.reflect.Method.invoke(Native Method)
                                                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                                              Caused by: java.lang.IllegalStateException: com.kaushik.myredmart.di.AppModule must be set
                                                 at com.kaushik.myredmart.di.DaggerAppComponent$Builder.build(DaggerAppComponent.java:180)
                                                 at com.kaushik.myredmart.di.AppInjector.init(AppInjector.java:30)
                                                 at com.kaushik.myredmart.MartApplication.onCreate(MartApplication.java:28)
                                                 at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1013)
                                                 at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4707)
                                                 at android.app.ActivityThread.-wrap1(ActivityThread.java) 
                                                 at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1405) 
                                                 at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                 at android.os.Looper.loop(Looper.java:148) 
                                                 at android.app.ActivityThread.main(ActivityThread.java:5417) 
                                                 at java.lang.reflect.Method.invoke(Native Method)

Benutzer-Avatar
Azizbekisch

Ich glaube du hast vergessen zu setzen @ContributesAndroidInjector Anmerkung:


    @Module
    public abstract class ActivityModule {
        @ContributesAndroidInjector
        abstract ProductListActivity contributeProductListActivity();
        @ContributesAndroidInjector
        abstract ProductDetailsActivity contributeProductDetailsActivity();
    }

Und beinhalten ViewModelModule innerhalb AppModule:


    @Module(includes = ViewModelModule.class)
    class AppModule {
        ...
    }


Sehen Sie sich diesen Code an, den Sie geschrieben haben:

@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepository repository) {
    return repository;
}

Was erwartest du? Du sagst Dolch „Hey, Dolch, wann immer ich dich bitte, mich zu versorgen ProductListRepository dann erstellen (zurückgeben) dieses Objekt mit ProductListRepository. Das wird nicht klappen.

Höchstwahrscheinlich war das, was Sie beabsichtigten „Hey, Dolch, wann immer ich dich bitte, mir eine Implementierung von bereitzustellen ProductListRepository dann erstellen (zurückgeben) dieses Objekt mit ProductListRepositoryImpl:

@Provides
@Singleton
ProductListRepository provideProductListRepository(ProductListRepositoryImpl repository) {
    return repository;
}

Was durch Folgendes ersetzt werden kann:

@Binds
@Singleton
abstract ProductListRepository provideProductListRepository(ProductListRepositoryImpl repository);

  • Ich habe es versucht. Bitte überprüfen Sie meinen bearbeiteten Teil oben und die Anleitung.

    – dev_android

    26. Juli 2017 um 18:00 Uhr

  • Ich bin dir gefolgt, das hat zu einem Abhängigkeitszyklus geführt. Bitte beraten.

    – dev_android

    26. Juli 2017 um 18:23 Uhr

  • Oben im bearbeiteten Teil hinzugefügt. Bitte überprüfen Sie @azizbekian

    – dev_android

    26. Juli 2017 um 18:44 Uhr

  • Danke für die Erklärung. Abhängigkeitsproblem gelöst, aber Ausnahme beim Ausführen: Anwendung com.mymart.MartApplication kann nicht erstellt werden: java.lang.IllegalStateException: com.mymart.di.AppModule muss festgelegt werden

    – dev_android

    26. Juli 2017 um 19:59 Uhr

  • Siehe einige Tutorials. Du hattest viele Probleme.

    – Azizbekisch

    27. Juli 2017 um 2:40 Uhr

Benutzer-Avatar
Caner

Für diesen Fehler: “Dolch: IllegalArgumentException: Keine Injektorfabrik für Klasse gebunden

Wenn Sie verwenden Navigationskomponente mit Einzelne Aktivitätkönnen Sie diesen Fehler sehen.

Was tun?

Bitte prüfe dein @Module abstrakte Klasse FragmentProvider { … } da Sie Ihr Fragment darin als Contribute hinzufügen müssen.

@Module
abstract class FragmentProvider {

  @ContributesAndroidInjector // <- Do not forget this line.
  abstract fun contributeYourNewFragment(): YourNewFragment
}

Dagger2-Fehler sind einfacher als dagger1, aber sie werden nacheinander angezeigt, je nachdem, mit welchem ​​​​Problem Dolch zuerst in der Kompilierungszeit konfrontiert wird.

Sie sind mit Ihren Lösungen auf mehr als den obigen Fehler gestoßen:

  • 1. Fehler: Dolch: IllegalArgumentException: Keine Injektorfabrik für Klasse gebunden

und das liegt daran, dass Sie Dolch mit Aktivität im ActivityModule bereitstellen, ohne die Anmerkung @ContributesAndroidInjector hinzuzufügen

Diese Anmerkung muss auf eine abstrakte Methode in einem Modul angewendet werden, das einen konkreten Android-Framework-Typ zurückgibt.“ dh Aktivität / Fragment usw.

@Module
public abstract class ActivityModule {
    @ContributesAndroidInjector
    abstract ProductListActivity contributeProductListActivity();
    @ContributesAndroidInjector
    abstract ProductDetailsActivity contributeProductDetailsActivity();
}

Ref

  • 2. Fehler: java.lang.IllegalStateException: AppModule must set at DaggerAppComponent$Builder.build(DaggerAppComponent.java:180)

Wenn Ihr AppModule keinen Standardkonstruktor hat, kann Dagger keine Instanz von AppModule erstellen. Erstellen Sie also eine AppModule-Instanz und setzen Sie sie auf Dagger-Diagramm.

 mComponent = DaggerXComponent.builder()
    .appModule(new AppModule(....)) // create appModule instance
    .build();

Wenn Module keinen benutzerdefinierten Konstruktor haben, erstellt Dagger bei Bedarf automatisch eine Instanz über den Standardkonstruktor.

Finden Sie diese Antwort

Sie können dies sehen, wenn Sie Java-Schlüsselwörter wie verwenden new oder short, longusw. in Ihren Paketnamen (auch wenn Sie Kotlin in Ihrer gesamten App verwenden).

Dagger generiert Java-Code für Ihre Definition und Klassen. Diese Codegenerierung schlägt für Paketnamen fehl, die reservierten Java-Schlüsselwörtern entsprechen. Zum Beispiel, wenn Sie ein Paket haben your.app.com.paywall.new.ui, schlägt die Codegenerierung im Hintergrund fehl, die erforderlichen Dagger-Klassen und -Methoden zu generieren. Aus diesem Grund sehen Sie diese Ausnahme nur zur Laufzeit.

Benutzer-Avatar
Göttliches Chaos

Die Verwendung des @contrubutesAndroidInjector erfordert einen zusätzlichen annotationProcessor.

Fügen Sie diese Zeile zu Ihrer Gradle-Build-Datei hinzu:

annotationProcessor 'com.google.dagger:dagger-android-processor:2.11'

1245700cookie-checkDolch: IllegalArgumentException: Keine Injektorfabrik für Klasse gebunden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy