How to get the reference of the graph built using Dagger2 DI?

166 views
Skip to first unread message

Ravjit Singh Uppal

unread,
Jan 29, 2016, 6:55:01 AM1/29/16
to Dagger Discuss
I have an PerActivity component. I build the graph in the onCreate of the activity like this:

     mActivityComponent = DaggerActivityComponent.builder()
                .appComponent(BrowserApp.getAppComponent())
                .activityModule(new ActivityModule())
                .build();

It is pretty straight forward to get reference of `mActivityComponent` in fragments. I can use this for it:

    ((MainActivity)getActivity()).getActivityComponent();

The problem arises in other classes. Let's say I have a webView which doesn't have a method like `getActivity()`. How should I get a reference to `mActivityComponent`? If I pass the reference in the constructor, doesn't it defeat the purpose of using Dependency Injection?
And I cannot make it static, because then it won't be "PerActivity" anymore, it will be one and same for all activities.

Dino Wernli

unread,
Jan 31, 2016, 9:36:55 AM1/31/16
to dagger-...@googlegroups.com
Hi Ravjit

I'm just a user of Dagger, so I would also be interested in whether there is an officially recommended solution to this. I can, however, share the workaround I am currently using. In order to be able to inject a MyComponent, I introduced an injectable singleton class BootstrapHelper which contains an Optional<MyComponent>. Immediately after creating the component, I grab its BootstrapHelper and set the contained component to the MyComponent instance just created.

That way, anything in the graph of provided types can just inject the BootstrapHelper and and get access to the component. The only thing which is a bit ugly is that it requires this stateful helper which needs to be initialized immediately after creating the component. Also, it's worth considering that injecting the component itself kind of indicates a bit of a smell and should probably be used very sparingly, so it could be that this "feature" was left out on purpose. 

So as I said, it works even if it's not super pretty. But I would be interested in how the Dagger folks recommend solving this :)

Cheers
Dino


--
You received this message because you are subscribed to the Google Groups "Dagger Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dagger-discus...@googlegroups.com.
To post to this group, send email to dagger-...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Thomas Broyer

unread,
Jan 31, 2016, 10:07:38 AM1/31/16
to Dagger Discuss
Disclaimer: I'm not an Android developer.


On Friday, January 29, 2016 at 12:55:01 PM UTC+1, Ravjit Singh Uppal wrote:
I have an PerActivity component. I build the graph in the onCreate of the activity like this:

     mActivityComponent = DaggerActivityComponent.builder()
                .appComponent(BrowserApp.getAppComponent())
                .activityModule(new ActivityModule())
                .build();

It is pretty straight forward to get reference of `mActivityComponent` in fragments. I can use this for it:

    ((MainActivity)getActivity()).getActivityComponent();

The problem arises in other classes. Let's say I have a webView which doesn't have a method like `getActivity()`. How should I get a reference to `mActivityComponent`? If I pass the reference in the constructor, doesn't it defeat the purpose of using Dependency Injection?

If you are in a situation where you can pass something in the constructor, then chances are you should not call "new" yourself and let Dagger do it and inject whatever dependency is needed (i.e. not the component itself).
And even if "new'ing" the object yourself, you probably shouldn't pass it the component but rather the object's dependencies (aka "manual DI")

Ron Shapiro

unread,
Jan 31, 2016, 11:57:47 PM1/31/16
to Dagger Discuss
This all depends on where you want to store your component, but this raises a larger design question that you should always consider: how do I want clients of the component to know about the component itself? Storing a component in a static field raises so many design anti-patterns, and thus any other solution requires consideration of what the component <--> webview relationship (in your example) should be. What types should know about others? Here's one option:
  • Have the logical owner of the objects like the web view in your example hand a reference to the component. This could be something like: 
      // MainActivity:
      ActivityComponent component = DaggerActivityComponent.builder()...
      setContentView(R.layout.blah);
      YourCustomWebView webView = findViewById();
      webView.setComponent(activityComponent);
      // or you can invoke the members injector directly: activityComponent.inject(webView);

--
Reply all
Reply to author
Forward
0 new messages