dagger2 error “android.app.Application cannot be provided without an @Inject constructor or from an @Provides-annotated method”

梦想与她 提交于 2019-12-04 03:28:07

问题


I'm trying to implement dagger2 in my project, but I'm faced with an error "android.app.Application cannot be provided without an @Inject constructor or from an @Provides-annotated method".

Here's my code:

App.java

package com.poppmedia.wallpaperautomaton;

import android.app.Application;

import com.poppmedia.wallpaperautomaton.di.DaggerAppComponent;

import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;

/**
 * The Android {@link Application}.
 */
public class App extends DaggerApplication {
    @Override
    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        return DaggerAppComponent.builder().create(this);
    }
}

di/AppModule.java

package com.poppmedia.wallpaperautomaton.di;

import android.app.Application;
import android.content.Context;

import javax.inject.Singleton;

import dagger.Binds;
import dagger.Module;

/**
 * Provider application-wide dependencies.
 */
@Module
public interface AppModule {
    @Binds
    @Singleton
    Context bindContext(Application application);
}

di/AppComponent.java

package com.poppmedia.wallpaperautomaton.di;

import com.poppmedia.wallpaperautomaton.App;

import javax.inject.Singleton;

import dagger.Component;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;

/**
 * Injects application dependencies.
 */
@Singleton
@Component(modules = {
        AndroidSupportInjectionModule.class,
        AppModule.class,
})
public interface AppComponent extends AndroidInjector<App> {
    @Component.Builder
    abstract class Builder extends AndroidInjector.Builder<App> {}
}

di/TestClassModule.java

package com.poppmedia.wallpaperautomaton.di;

import android.content.Context;

import com.poppmedia.wallpaperautomaton.TestClass;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module
public class TestClassModule {
    @Provides
    @Singleton
    TestClass provideTestClass(Context context) {
        return new TestClass(context);
    }
}

di/TestClassComponent.java

package com.poppmedia.wallpaperautomaton.di;

import com.poppmedia.wallpaperautomaton.TestClass;

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(modules = { AppModule.class, TestClassModule.class })
public interface TestClassComponent {
    TestClass getTestClass();
}

TestClass.java

package com.poppmedia.wallpaperautomaton;

import android.content.Context;

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

@Singleton
public class TestClass {
    private Context mContext;

    @Inject
    public TestClass(Context context) {
        mContext = context;
    }
}

Thank you.


回答1:


In your specific case, you're missing:

@Binds Application bindApplication(App app);

This is important because dagger.android will automatically include a binding to the specific Application, Activity, Fragment, Service, BroadcastReceiver, etc subclass but not the general object. (You'd be able to inject App but not Application, and YourActivity but not Activity.) If you want to indicate to dagger.android that it should fulfill requests for Application using your App instance, you have to include a binding as above.

Generally speaking, this is a pretty safe thing to do for Application, Activity, Service, and BroadcastReceiver, but not Fragment (native or in the compat libraries); this is because dagger.android respects nested fragments, and in that case it would be ambiguous which Fragment to inject.

Though you can provide the Application through a Module and instance field as in luffy's answer, this is more boilerplate than you need, and is also less optimized: Dagger will write code to call your @Provides method, whereas you can declaratively tell Dagger to reuse an existing binding using @Binds or write a static @Provides method that avoids invoking the call on an instance.

See the Dagger advantages of @Binds and the Android advantages of static dispatch.




回答2:


In AppModule, you @Binds a Application, but Application is not provide by any other module.

Because the Application is created by Android framework, you should let AppModule provide the Application from outside.

@Module
public class AppModule {
    private Application mApp;
    public AppModule(Application app) {
        mApp = app
    }
    @Singleton
    Context provideContext() {
        return mApp
    }
}


来源:https://stackoverflow.com/questions/47940187/dagger2-error-android-app-application-cannot-be-provided-without-an-inject-con

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!