Dagger 2 activity injection not working

2019-05-11 09:08发布

问题:

I'm trying the new dagger 2, it's my first time implementing it but I can't make it work. I think I got the concept and I understand the example here

I try to copy the same structure just a bit modified for my example.

Here is the AppComponent that extends the Graph where I defined the classes I want.

@ApplicationScope
@Component(modules = {AppModule.class, DataModule.class})
public interface EFAppComponent extends EFGraph {

    /**
     * An initializer that creates the graph from an application.
     */
    public final static class Initializer {

        private Initializer() {
        } // No instances.

        public static EFAppComponent init(EFApp app) {
            return Dagger_EFAppComponent.builder()
                    .appModule(new AppModule(app))
                    .build();
        }
    }
}


public interface EFGraph {

    public void inject(EFApp app);

    public ImageLoader imageLoader();

    public EventBus eventBus();

}

Then inside each module I'm providing the corresponding classes. From here everything works good and Dagger seams to build the Dagger_EFAppComponent correctly.

Then in the Application class I init using the constructor

component = EFAppComponent.Initializer.init(this);
component.inject(this);

Then my goal is to Inject ImageLoader and EventBus in my activity. To do that I create a ActivityComponent.

@ActivityScope
@Component(
        dependencies = EFAppComponent.class,
        modules = ActivityModule.class
)
public interface ActivityComponent {

    public void inject(BaseActivity activity);

}

Then from my activity I call inject.

activityComponent = Dagger_ActivityComponent.builder()
                .eFAppComponent(component)
                .activityModule(new ActivityModule(this))
                .build();
activityComponent.inject(this);

So because I declared @Inject EventBus eventBus in my activity after the inject method call should be injected. Well it's not.

So after debugging and tracking step by step my app and the example I realized that the Dagger_ActivityComponent is not build correctly.

private final ActivityModule activityModule;
    private final EFAppComponent eFAppComponent;

    private Dagger_ActivityComponent(Builder builder) {  
        assert builder != null;
        this.activityModule = builder.activityModule;
        this.eFAppComponent = builder.eFAppComponent;
        initialize();
  }

Were the initialize method is empty and no Provider are declared as variable.

Am I missing something? I've been the full day trying to make it work but I'm not success.

Appreciate the help.

回答1:

Well... After the full day spend on this I decide to post it and after 5 minutes I found the solution.

I'm using a BaseActivity for all my activity, and I thought I could use this to inject my components but seams this is not possible.

So I just change this line in my ActivityComponent

public void inject(BaseActivity activity) 

to

public void inject(MainActivity activity) 

So to the name of the activity where I'm injecting the dependencies...

What brings me to a new question. How can I implement a base component to handle all my activities? or I must create a Component for each view/activity/fragment I want to have DI?



回答2:

@Marcel, I recently migrated a project from Dagger 1.2 over to 2.0. I had similar solution where abstract BaseActivity injected the dependencies by doing something along the lines of "application.inject(this);". With Dagger 2.0 this is not possible (as of now) as mentioned in the comment above.

One of the ways I got around this was by changing the "inject" method in the Application class itself to strong type the object. For Example..

class MyApp extends Application {
   ...
   public void inject(Object activity) {
    if (activity instanceof MainActivity) {
      mComponent.inject((MainActivity) activity);
    } else if (activity instanceof SubActivity) {
      mComponent.inject((SubActivity) activity);
    }
  }
}

With that I did not have to change anything in my existing classes.

FYI: There is a project called Bullet by @thomas-broyer that does this too.