Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.lang.IllegalArgumentException: No injector factory bound for Class<MyActivity_>

The error I have is following:

Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class. Injector factories were bound for supertypes of MyActivity_: [MyActivity]. Did you mean to bind an injector factory for the subtype?

As I understand it happens because I am using an AndroidAnnotations library.

AppComponent.class :

@Singleton
@Component(modules = {
    AndroidInjectionModule.class,
    AppModule.class,
    ActivityBindingModule.class })
public interface AppComponent extends AndroidInjector<DaggerApplication> {

    @Component.Builder
    interface Builder {
         @BindsInstance Builder application(Application application);
         AppComponent build();
    }

    void inject(Application application);

    @Override
    void inject(DaggerApplication instance);
}

AppModule.class :

@Module
public abstract class AppModule {

    @Binds
    abstract Context provideContext(Application application);

    @Provides
    @Singleton
    static SharedPreferencesManager providesPreferences(Application application){
        return SharedPreferencesManager_.getInstance_(application);
    }
}

ActivityBindingModule.class :

@Module
public abstract class ActivityBindingModule {

    @ContributesAndroidInjector(modules = LoginActivityModule.class)
    @LoginActivityScope
    abstract LoginActivity bindLoginActivity();
}

Application.class :

@EApplication
public class Application extends DaggerApplication {

    @Inject
    DispatchingAndroidInjector<Activity> activityDispatchingAndroidInjector;

    protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
        AppComponent appComponent = DaggerAppComponent.builder()
            .application(this)
            .build();

        appComponent.inject(this);
        return appComponent;
    }
}

LoginActivityModule.class

@Module
public class LoginActivityModule {

    @Provides
    @LoginActivityScope
    @ActivityContext
    public Context providesContext(LoginActivity loginActivity){
        return loginActivity;
    }

    @Provides
    @LoginActivityScope
    public LoginViewModel providesLoginViewModel(TelephonyManager telephonyManager,
                                             LoginModel loginModel,
                                             SharedPreferencesManager sharedPreferencesManager,
                                             LoginRemoteRepository loginRemoteRepository){
        return new LoginViewModel(telephonyManager, loginModel, sharedPreferencesManager, loginRemoteRepository,
            new CompositeSubscription());
    }

    @Provides
    @LoginActivityScope
    public LoginRemoteRepository providesRemoteRepository(@ActivityContext Context context,
                                                      MainApi mainApi,
                                                      SharedPreferencesManager sharedPreferencesManager){
        return new LoginRemoteRepository(mainApi, sharedPreferencesManager, context.getContentResolver());
    }

    @Provides
    @LoginActivityScope
    public LoginModel provideLoginModel(){
        return new LoginModel();
    }

    @Provides
    @LoginActivityScope
    public TelephonyManager provideTelephonyManager(Context context){
        return (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    }
}

LoginActivity.class :

@EActivity(R.layout.activity_login)
public class LoginActivity {

    @Inject
    LoginViewModel loginViewModel;

    @AfterViews
    void afterViews(){
        AndroidInjection.inject(this);
    }
}
like image 387
aleksandrbel Avatar asked Jan 05 '18 08:01

aleksandrbel


2 Answers

How to deal with Dagger 2 error: "Injector factories were bound for supertypes of ... Did you mean to bind an injector factory for the subtype?"

  1. Suppose we do have some BaseActivity:

    open class BaseActivity : MvpAppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        }
    }
    

We do also have an ActivityBuilder Module (which provides the BaseActivity itself) and we have a Module which provides the dependencies needed for the successful running of the BaseActivity.

@Module
abstract class ActivityBuilder {
    @ContributesAndroidInjector(modules = [BaseModule::class])
    abstract fun bindBaseActivity(): BaseActivity
}
  1. If we will add a ChildActivity like that

    class ChildActivity : BaseActivity() { }

thinking: "Hey, Dagger 2 will satisfy the dependencies for the BaseActivity and since we are extending it, we will get a ChildActivity up and running, right?". Wrong. We will get an exception "Injector factories were bound for supertypes of ... Did you mean to bind an injector factory for the subtype?"

  1. What we should do? We should make Dagger 2 know explicitly about our ChildActivity.

a) Add AndroidInjection.inject(this) to the ChildActivity onCreate() method:

class ChildActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
    }
}

b) add all subclasses of the BaseActivity to the ActivityBuilder module (which provides activities). Note, that the BaseModule, satisfying dependencies for the BaseActivity, should also be included to the @ContributesAndroidInjector of the child class (ChildActivity)

@Module
abstract class ActivityBuilder {
    @ContributesAndroidInjector(modules = [BaseModule::class])
    abstract fun bindBaseActivity(): BaseActivity

    //Adding subclasses
    @ContributesAndroidInjector(modules = [BaseModule::class])
    abstract fun bindChildActivity(): ChildActivity
}
like image 83
Alex Burov Avatar answered Oct 02 '22 19:10

Alex Burov


Just an informed guess: It probably happens because your Class is actually called different when you use AndroidAnnotations (they add the underscore somewhere). Then you have to define the binding also like so (not sure where the underscore goes):

@ContributesAndroidInjector(modules = LoginActivityModule_.class)
@LoginActivityScope
abstract LoginActivity bindLoginActivity();
like image 41
Hendrik Marx Avatar answered Oct 02 '22 21:10

Hendrik Marx