This tutorial shows how to add dependencies to actions using Dagger 2 AndroidInjectionModule— for a very simple example. My use case is a little trickier:
- App extends Application implements HasDispatchingActivityInjector,
- ActivityOnewhich is initialized with- ActivityModule. Using this action, a dependency is created- DepOne,
- ActivityTwo, which has a dependency- DepTwothat cannot be correctly initialized without an existing one- DepOne.
The solution I came across is:
- Create AppComponentas the main component of the application,
- Create ComponentTwoas a subcomponentAppComponent. Add it at runtime as soon asDepOneavailable, and indicateDepTwoin it,
- Paste in ActivityTwoinsideComponentTwo.
This, however, requires that ActivityModule, which currently looks like this:
@Module(subcomponents = {
    ActivityOneSubcomponent.class,
    ActivityTwoSubcomponent.class
})
public abstract class ActivityModule {
    @Binds
    @IntoMap
    @ActivityKey(ActivityOne.class)
    abstract AndroidInjector.Factory<? extends Activity> bindLoginActivityInjectorFactory(ActivityOneSubcomponent.Builder builder);
    @Binds
    @IntoMap
    @ActivityKey(ActivityTwo.class)
    abstract AndroidInjector.Factory<? extends Activity> bindWorldActivityInjectorFactory(ActivityTwoSubcomponent.Builder builder);
}
breaks down into two different modules: one for ActivityOneand related to AppComponent, and the other for ActivityTwo(and other future activities) related to ComponentTwo.
I did this, but Dagger protests at run time when trying to enter ActivityTwo:
Caused by: java.lang.IllegalArgumentException: No injector factory bound for Class<ActivityTwo>
It looks like the application cannot see the factory injector provided by the added subcomponent.
Any ideas / hints?
Edit: I am sending the playback code below, as requested (in fact, there are no properties for injections like Dagger-injectable):
ActivityOne.java
public class ActivityOne extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        enterPartTwo();
    }
    private void enterPartTwo() {
        App.app(this).makeComponentTwo();
        ActivityTwo.start(this);
        finish();
    }
}
ActivityOneModule.java
@Module(subcomponents = {
        ActivityOneSubcomponent.class
})
public abstract class ActivityOneModule {
    @Binds
    @IntoMap
    @ActivityKey(ActivityOne.class)
    abstract AndroidInjector.Factory<? extends Activity> bindActivityOneInjectorFactory(ActivityOneSubcomponent.Builder builder);
}
ActivityOneSubcomponent.java
@Subcomponent
public interface ActivityOneSubcomponent extends AndroidInjector<ActivityOne> {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<ActivityOne> {}
}
ActivityTwo.java
public class ActivityTwo extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        AndroidInjection.inject(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_world);
    }
    public static void start(Context from) {
        Intent intent = new Intent(from, ActivityTwo.class);
        from.startActivity(intent);
    }
}
ActivityTwoModule.java
@Module(subcomponents = {
        ActivityTwoSubcomponent.class
})
public abstract class ActivityTwoModule {
    @Binds
    @IntoMap
    @ActivityKey(ActivityTwo.class)
    abstract AndroidInjector.Factory<? extends Activity> bindActivityTwoInjectorFactory(ActivityTwoSubcomponent.Builder builder);
}
ActivityTwoSubcomponent.java
@Subcomponent
public interface ActivityTwoSubcomponent extends AndroidInjector<ActivityTwo> {
    @Subcomponent.Builder
    abstract class Builder extends AndroidInjector.Builder<ActivityTwo> {}
}
App.java
public class App extends Application implements HasDispatchingActivityInjector {
    @Inject
    DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
    AppComponent appComponent;
    ComponentTwo componentTwo;
    @Override
    public void onCreate() {
        super.onCreate();
        appComponent = DaggerAppComponent.create();
        appComponent.inject(this);
    }
    @Override
    public DispatchingAndroidInjector<Activity> activityInjector() {
        return dispatchingAndroidInjector;
    }
    public void makeComponentTwo() {
        componentTwo = appComponent.inGameComponent()
                .build();
    }
    public static App app(Context context) {
        return (App) context.getApplicationContext();
    }
}
AppComponent.java
@Singleton
@Component(modules = {ActivityOneModule.class,
        AndroidInjectionModule.class})
public interface AppComponent {
    void inject(App app);
    ComponentTwo.Builder inGameComponent();
}
ComponentTwo.java
@ScopeTwo
@Subcomponent(modules = {ActivityTwoModule.class})
public interface ComponentTwo {
    @Subcomponent.Builder
    interface Builder {
        ComponentTwo build();
    }
}
ScopeTwo.java
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface ScopeTwo {
}
:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.abc, PID: 5923
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.abc/com.example.abc.ActivityTwo}: java.lang.IllegalArgumentException: No injector factory bound for Class<com.example.abc.ActivityTwo>
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
   at android.app.ActivityThread.-wrap11(ActivityThread.java)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
   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.IllegalArgumentException: No injector factory bound for Class<com.example.abc.ActivityTwo>
   at dagger.android.DispatchingAndroidInjector.inject(DispatchingAndroidInjector.java:105)
   at dagger.android.AndroidInjection.inject(AndroidInjection.java:61)
   at com.example.abc.ActivityTwo.onCreate(ActivityTwo.java:22)
   at android.app.Activity.performCreate(Activity.java:6237)
   at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
   at android.app.ActivityThread.-wrap11(ActivityThread.java) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
   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)
, .