Home » Android » android – java.lang.IllegalArgumentException: No injector factory bound for Class<MyActivity_>

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

Posted by: admin June 15, 2020 Leave a comment

Questions:

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);
    }
}
How to&Answers:

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();

Answer:

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
}