Dagger: AndroidInjection / AndroidSupportInjection to inject custom class

Created on 26 May 2017  路  8Comments  路  Source: google/dagger

Is it possible to do that with the android utilities ? I have an: Application / Activity / Fragment component structure where my activity components are subcomponents of the application component, and the fragments components are subcomponents for the activities ones. Everything is working alright using:

AndroidInjection.inject(this) for activities and AndroidSupportInjection.inject(this) for fragments inside onCreate and onAttach respectively:

// for the activity
override fun onCreate(savedInstanceState: Bundle?) {
    AndroidInjection.inject(this)
    super.onCreate(savedInstanceState)
}

// for fragments
override fun onAttach(context: Context?) {
    AndroidSupportInjection.inject(this)
    super.onAttach(context)
}

Injection works perfectly, but now I need to inject a different class using the fragment component. Is there any possible way to have access to the fragment / activity component from inside the activity / fragment and perform an injection over a different class? Let's say it's a customview with some injected dependencies, and I don't want to create a different component for it (since that would be messy and I don't really need to create a different scope for it, I should probably reuse the fragment / activity scope to inject it):

fragmentComponent.inject(myCustomView)

I would love to be able to do that in some way, but I see that AndroidInjection and AndroidSupportInjection are hiding too many details here and I the only possible choice for me to get this working would be to rollback the injection strategy to the "old style" explicit subcomponent builders inside the activity and the fragment.

Most helpful comment

If it's a class that Android constructs, you can inject the component into the fragment, and the fragment can call the injection:

@Subcomponent
interface FragSubcomponent extends AndroidInjector<Frag> {
  void inject(MyCustomView view);
  /* component builder */
}

class Frag extends DaggerFragment {
  @Inject FragSubcomponent component;

  void onCreateView() {
    component.inject(findViewById(R.id.customView));
  }
}

If the object is something that you can call new on, can you inject the type yourself?

All 8 comments

If it's a class that Android constructs, you can inject the component into the fragment, and the fragment can call the injection:

@Subcomponent
interface FragSubcomponent extends AndroidInjector<Frag> {
  void inject(MyCustomView view);
  /* component builder */
}

class Frag extends DaggerFragment {
  @Inject FragSubcomponent component;

  void onCreateView() {
    component.inject(findViewById(R.id.customView));
  }
}

If the object is something that you can call new on, can you inject the type yourself?

Perfect! I wasn't aware that you are able to inject the component itself into the fragment to get access to it. This is exactly what I was looking for.

Thanks for your help!

Or you could inject a MembersInjector<MyCustomView> rather than the full component.

How would that MembersInjector<MyCustomView>be attached to the fragment subcomponent scope to resolve it's dependencies using the fragment component?

It's injected by that component, so it resolves the dependencies in the same way.

Having a members-injection method on a (sub)component and injecting that (sub)component to call the method should be strictly equivalent to injecting a MembersInjector (i.e. from Ron's code, remove the void inject(MyCustomView view); from the subcomponent and replace @Inject FragSubcomponent with @Inject MembersInjector<MyCustomView>; it should have the same behavior)

Good to know. Thanks for the info guys!

Having a members-injection method on a (sub)component and injecting that (sub)component to call the method should be strictly equivalent to injecting a MembersInjector

Soon, that won't be the case as that we'll be inlining members injection methods. So you'll save on the creation of the MembersInjector object and Providers for all of the dependencies

Soon, that won't be the case as that we'll be inlining members injection methods. So you'll save on the creation of the MembersInjector object and Providers for all of the dependencies

Ah yes, in terms of optimisations, though the behavior stays the same.

Was this page helpful?
0 / 5 - 0 ratings