4

I am new to Dagger 2. I have already tried to set up the same. Here is my ActivityModule :

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

    @ContributesAndroidInjector
    abstract ProductDetailsActivity contributeProductDetailsActivity();
}

My AppModule:

@Module
class AppModule {

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

My 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);
}

My Application:

public class MartApplication extends Application implements HasActivityInjector {

    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;

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

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

In AppInjector:

public class AppInjector {
private AppInjector() {
}

public static void init(MartApplication application) {
    DaggerAppComponent.builder().application(application)
            .build().inject(application);
    application
            .registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                    handleActivity(activity);
                }

                ............
            });
}

private static void handleActivity(Activity activity) {
    if (activity instanceof Injectable) { //HasSupportFragmentInjector) {
        AndroidInjection.inject(activity);
    }
    if (activity instanceof FragmentActivity) {
        ((FragmentActivity) activity).getSupportFragmentManager()
                .registerFragmentLifecycleCallbacks(
                        new FragmentManager.FragmentLifecycleCallbacks() {
                            @Override
                            public void onFragmentCreated(FragmentManager fm, Fragment f,
                                                          Bundle savedInstanceState) {
                                if (f instanceof Injectable) {
                                    AndroidSupportInjection.inject(f);
                                }
                            }
                        }, true);
    }
}

}

It is throwing an exception on inject:

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.mymart.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)

Can anyone help me to get an idea where actually the problem in my set up?

dev_android
  • 8,698
  • 22
  • 91
  • 148

4 Answers4

7

I believe AppModule must be set in the AppComponent's Builder interface and should be provided while creating AppComponent.

AppComponent:

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

        Builder appModule(AppModule appModule); // add this

        AppComponent build();
    }

    void inject(MartApplication martApp);
}

AppInjector:

Inside init method:

DaggerAppComponent.builder()
.application(application)
.appModule(new AppModule()) // add this
.build()
.inject(application);
Mustafa Berkay Mutlu
  • 1,929
  • 1
  • 25
  • 37
1

You need to add @ContributesAndroidInjector to your abstract methods in the ActivityModule

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

    @ContributesAndroidInjector
    abstract ProductDetailsActivity contributeProductDetailsActivity();
}
MatPag
  • 41,742
  • 14
  • 105
  • 114
  • I wonder why op [always removes](https://stackoverflow.com/questions/45326775/dagger-illegalargumentexception-no-injector-factory-bound-for-class/45327464#45327464) that annotation – azizbekian Jul 27 '17 at 12:12
  • Lol, you are right :D i +1'd your answer because was already correct – MatPag Jul 27 '17 at 12:14
  • I forget to mention in question. It was already there in Studio. – dev_android Jul 27 '17 at 12:15
0

The Kotlin version. AppComponent.kt:

import com.domain.app_name.core.domain.App
import com.domain.app_name.splash.di.SplashModule
import com.domain.app_name.splash.presentation.BusinessLoginBottomSheet
import dagger.Component
import dagger.android.AndroidInjectionModule
import javax.inject.Singleton
import dagger.BindsInstance

@Singleton
@Component(modules = [
    AndroidInjectionModule::class,
    AppModule::class,
    SplashModule::class
])
interface AppComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance
        fun app(app : App) : Builder
        fun appModule(appModule : AppModule) : Builder
        fun build() : AppComponent
    }

    fun inject(app : App)
    fun inject(businessLoginBottomSheet : BusinessLoginBottomSheet)
    fun inject(appModule : AppModule)
}

App.kt:

import android.app.Application
import com.domain.app_name.core.di.AppModule
import com.domain.app_name.core.di.DaggerAppComponent
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import javax.inject.Inject

class App : Application(), HasAndroidInjector {

    @Inject
    lateinit var injector: DispatchingAndroidInjector<Any>

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.builder()
            .app(this)
            .appModule(AppModule(this))
            .build()
            .inject(this)
    }

    override fun androidInjector() : AndroidInjector<Any> {
        return injector
    }
}
Barakuda
  • 790
  • 8
  • 16
-1

The whole structure of your Di seems kind of odd. Any particular reason for using all of those complications (having in mind that you say that you are new to Dagger and all tutorials of it don't have anything close to your implementation)?

jujka
  • 1,190
  • 13
  • 18
  • 2
    I am trying to implement Google new architecture components using Dagger 2. I am actually followed GithubBrowserSample given by GoogleSamples – dev_android Jul 27 '17 at 12:07