Dagger - Inject provide beans both to field variable and constructor at same this - dagger

I have a class with the following structure.
Is it "legal" in Dagger to #Inject beans in field variables and constructors at the same time, as I have done below? If no - I have a MyActivityModule and MyApplicationModule, how can I get the dependencies from MyApplicationModule and add them to the constructor I use in the provideWhatEvery in the MyActivityModule ?
#Inject SmsFormatter mSmsFormatter;
#Inject SmsGuardiansUtils smsGuardiansUtils;
#Inject BipperMediaPlayer bipperMediaPlayer;
#Inject MixPanelUtils mMixpanelUtils;
#Inject
public ImHereController(View view, Context context, AlarmModel alarmModel, ActionBarListener actionBarListener,
FragmentController fragmentController){
super(view, context, alarmModel, actionBarListener, fragmentController);
}

You can inject fields and constructors as you have. The constructor parameters will be resolved first and injected upon construction, and after that the fields will be injected.
The other parts of your question are unclear - it doesn't matter whether you add dependencies by field injection or constructor injection - if you wanted to add them all with constructor injection you could.
The only time you must use field injection is where you have an object whose instantiation you cannot control, and therefore dagger cannot itself instantiate (like Activity and Application subtypes.)
All that said, I would not use both without some compelling reason - constructor injection is more semantically clear and you can make the instance variables final. Alternately, field injection is more terse, and possibly more readable in cases. I would pick one, and not both.

Related

Dagger 2 inject subcomponent.builder

I'm seeing some code where a SubComponent.Builder is being injected. For instance:
class MyClass #Inject constructor(val mySubcomponentBuilder: MySubComponent.Builder) {
fun someFunc(knownAtRuntime: String) {
mySubcomponentBuilder.withSomethingIKnowAtRuntime(knownAtRuntime).build()
}
}
Why do we (and where/when should we) do this (i.e. inject subcomponent.builders)?
Is this sort of like assisted injection where we can provide instances that are needed on the graph that we only know during runtime?
Yes, a subcomponent builder is sort of like assisted injection, but for a whole subgraph of injectable Dagger dependencies.
What are subcomponents?
Subcomponents are additional components that derive from parent components. In Guice they are analogous to child injectors; in Dagger 1 they are analogous to subgraphs. They let you add additional bindings on top of the parent bindings, as specified through additional modules.
In the sense that they allow bindings from different graphs, they can be compared to component dependencies, but they are generated at the same time as the parent component and can transparently use bindings defined in the parent component. The dagger.android and Hilt packages both use subcomponents.
Each component can have their own scope, and subcomponents aren't an exception: you might see a #Singleton ApplicationComponent with a subcomponent of #RequestScope RequestComponent for servers or #ActivityScope ActivityComponent for Android. Each request or activity would get their own component instance. That would let you inject a #RequestScoped MetricsService or #ActivityScoped User, which would be the same instance within the same request/activity but different instances between the requests/activities.
What are subcomponent builders?
Subcomponents might require modules to be instantiated if they have non-empty constructors, or they might require instances to be bound through #BindsInstance. Subcomponent Builders allow you to specify those just like you would for a Component Builder.
You also have the choice of using a Subcomponent.Factory, analogous to Component.Factory but with all of the Builder parameters as the arguments to one method call.
Why would I inject subcomponent builders? What are the alternatives?
Though you can declare subcomponents as factory methods specified on the parent component, this prevents Dagger from pruning unused dependencies because it can't see who is requesting the subcomponent. By declaring subcomponents on modules and injecting their builders into the graph, Dagger can remove entire subcomponents if you don't call them at all.

Dagger does not fo injection with void method

I have app wide component (contains only Singletons), which is accesible by static method App.getComponent();. My component contains method void inject(MainActivity activity) and it works fine. I also have void inject(TaskRepo repo), but this one does not work. In TaskRepoImpl() I invoke: App.getComponent().inject(this);, but it does not injects anything. I'm sure that I annotated public members with #Inject.
Injecting with methods like TaskRepo repo = App.getComponent().taskRepo(); works fine. So why does Dagger ignores these members?
In short, you need the method to be void inject(TaskRepoImpl impl); you can't just accept TaskRepo. Your case is described in the Component docs under "A note about covariance".
Dagger is a compile-time framework: at compile time Dagger will take a look at your Component and write implementations based on the methods on your Component (and its Modules). Some of those methods might be members injection methods (same link as above), which are single-arg methods that set #Inject fields and call #Inject methods for the instance you pass in. These are typically void methods named inject, but they can be named anything, and they might also return the instance they inject (for chaining).
The trick is, Dagger can only anticipate the fields and methods on the specific type you define, not its subclasses: if you create a members-injection method void inject(Foo foo), then only Foo's fields and methods count, even if Foo's subclass Bar has #Inject-annotated methods. Even if your Dagger graph knows about both Foo and Bar, it would not know about other Foo subclasses, and would not necessarily be prepared to inject them (because all of that happens at compile time). This is also not a problem for "provision methods" (zero-arg factories/getters on Components) because as long as Dagger knows how to create a particular concrete type for a binding, it can inject that concrete type and simply return the reference as its supertype or interface.
Therefore, switching the injection to the actual implementation class avoids this problem, because Dagger can inspect the implementation class TaskRepoImpl at compile time and ensure it has the bindings that TaskRepoImpl defines in its #Inject-annotated methods and fields.
#Component(modules = {...}) public interface YourComponent {
/**
* Only injects the fields and methods on TaskRepo, which might do
* nothing--especially if TaskRepo is just an interface.
*/
void inject(TaskRepo taskRepo);
/**
* Injects the fields and methods on TaskRepoImpl, TaskRepo, and
* any other superclasses or interfaces.
*/
void inject(TaskRepoImpl taskRepoImpl);
/**
* Gets a TaskRepo implementation. If you've bound TaskRepo to TaskRepoImpl,
* Dagger _can_ inject all of TaskRepoImpl's fields, because it knows at
* compile time that there's a TaskRepoImpl instance to inject.
*/
TaskRepo taskRepo();
}
As a side note, constructor injection allows you to better-encapsulate your classes by using final fields and avoiding partially-constructed (constructed but not injected) instances. I recommend using constructor injection where possible, and recommend strongly against using field injection and constructor injection separately for the same type. (You're probably not doing this other than to debug your case, but I'm leaving the note here for future readers as well.)

In Dagger, does an Inject annotated class also act as a Provider?

I am new to Dagger (version 2.16 on Android) and based on my reading so far, I understand that for a component, there should be a provider (#Provides or #Binds) encapsulated in a module (#Module). Going through a lot of samples, I see code which has some objects which are not offered in any Module, nor are they being instantiated using new.
It is also my understanding that in order to access the dependencies in a module, a consumer class needs to inject itself in the component graph (components usually offer a method to inject classes). The code examples are not doing this either.
Here's some code demonstrating both my concerns. RecipePresenter is not being provided in any module, but still RecipeActivity is using it.
A possible explanation I could think of is that #Inject, in addition to requesting the dependency also adds/injects the requesting class (RecipePresenter in the linked code) into the component graph. But assuming there are multiple components/subcomponents, which component does the class using #Inject constructor gets attached to? If my understanding is correct, why do activities and fragments have to inject themselves manually in the component - shouldn't they be auto-injected if they declare a variable annotated with #Inject?
RecipePresenter has an #Inject-annotated constructor, which allows it to be provided. The #Inject annotation on the recipePresenter field within RecipeActivity does not help, just the #Inject-annotated constructor.
class RecipePresenter #Inject constructor(
private val useCase: RecipeUseCase,
private val res: StringRetriever) :
RecipeUseCase.Callback {
From the Dagger User's Guide:
Use #Inject to annotate the constructor that Dagger should use to create instances of a class. When a new instance is requested, Dagger will obtain the required parameters values and invoke this constructor.
If the class with the #Inject-annotated constructor also has a defined scope, then the binding will only affect components with the same scope annotation: An #ActivityScope class wouldn't be accessible from a #Singleton component, for instance. If the class has no scope defined, then the binding could appear on any and all components where it is needed, which is fine: The implementation is always the same, defined by the constructor itself.
#Inject has different meanings based on what it's annotating:
When you annotate a field with #Inject, it indicates that the DI system should set that field based on values from the DI system when it injects that object.
When you annotate a method with #Inject, it indicates that the DI system should call that method with parameters based on values from the DI system when it injects that object.
When you annotate a constructor with #Inject, it indicates that the DI system is allowed to call that constructor in order to create that object (which triggers the field and method injection above). In that sense it does act like a built-in Provider.
In Dagger specifically, #Provides methods take precedence over #Inject constructors (if they both exist for the same class), and unlike in the JSR-330 spec Dagger requires an #Inject-annotated constructor even when no other constructors are present. From the Dagger User's Guide:
If your class has #Inject-annotated fields but no #Inject-annotated constructor, Dagger will inject those fields if requested, but will not create new instances. Add a no-argument constructor with the #Inject annotation to indicate that Dagger may create instances as well.
Classes that lack #Inject annotations cannot be constructed by Dagger.
Finally, to answer your question about why activities and fragments need to inject themselves: Android is allowed to reflectively create Activity/Fragment/View objects without Dagger's help or participation. This means that nothing triggers the field and method injection described above, until you call a members-injection method on the component that instructs Dagger to populate those fields and call those methods. Consequently, you should never see an #Inject-annotated constructor on Application, Activity, Service, Fragment, View, ContentProvider, and BroadcastReceiver subclasses in Android: Android will ignore the #Inject annotation, so you might as well take control over injection yourself, manually or through dagger.android.

In Jersey 2.X, a Feature is instantiated by HK2. How can I use Factories I've also added?

In the strange, strange dependency injection world of Jersey, you can include an AbstractBinder (but maybe not just a Binder) as one of the objects in the return value of your Application's getSingletons() method.
That AbstractBinder can then call various bind() methods from within its configure() method, which Jersey, but no other JAX-RS implementation, is guaranteed to call—and hence you can link implementations to interfaces, which lets you do a semblance of dependency injection from that point forward in your application. That is, once you've done that, then injection points within, say, your resource classes will be "filled" by the implementations you've bound.
(You can also do this with factory classes, so that you bind a particular factory method's return value to a contract it implements.)
OK, fine.
Jersey also lets you place a Class that implements Feature into the return value of your Application's getClasses() method. Fine. This Feature class will be instantiated by HK2 under the covers—make a mental note of that!—and its configure(FeatureContext) method will be called at some point. At that point, the Feature may register some additional stuff by calling FeatureContext#register() and handing it whatever it wants to register.
(Presumably this is all a fairly complicated façade on top of HK2's DynamicConfiguration machinery.)
Anyway, since a Feature is instantiated by HK2 (remember?), it follows that you can #Inject things into its constructor, or have injection points elsewhere in the class. That's cool! Then HK2 can draw upon all the services it knows of to fill those injection points. Very neat.
Ah, but the question is: what is the state of the HK2 world at this point? What services can be injected into a Feature implementation instantiated as part of A JAX-RS Application's startup sequence?
If your Application's getSingletons() method returns an AbstractBinder implementation that binds a FooImpl to Foo in Singleton scope in its configure() method, can your Feature—"registered" by including its class in the return value of your Application's getClasses() method—then inject a Foo?
I think it is important to have your Foo interface binding proxied, i.e:
new AbstractBinder() {
#Override
protected void configure() {
bind(Foo.class)
.proxy(true)
.to(FooImpl.class)
.in(Singleton.class);
}
}
then dependency injection will be insensitive to the instatination order.

How to debug Dependency Injection Bugs in Extbase?

I'm building an extension in Extbase (latest version, latest typo3) and am having repositories injected into my models.
This simply does not work. No errors, no clues, nothing. The inject* Method simply does not get called. The exact same Injection works in the controller.
Is it possible to inject Repositories into models in Extbase? In general, injection to models is possible since 1.4.
How can I debug this? Where do I have to look?
This is a common misconception:
Not every class you use in TYPO3 CMS uses dependency injection by default - and it's a good thing.
What is true, is that every object that has been instantiated by the ObjectManager can benefit from it.
In short: if you new Thing() some object, it won't benefit from dependency injection. If you use the ObjectManager to get an instance of something, the whole dependency injection gallore will rain down on your new instance:
constructor injection [Example: How can I use an injected object in the constructor?
annotations are read and field injections are done
setter injection was done in the past (Remark: I think it's deprecated)
public method (if existent) initializeObject is called
Note that injected objects are being instantiated by the objectManager as well-so recursion is possible if injected ServiceA needs an injected ServiceB.
Singletons are possible as well if you implement the marker interface SingletonInterface.
Dependency injection only works if you get an instance of the object via the ObjectManager. If you are using the good ol'
t3lib_div::makeInstance('Tx_yourextension_domain_model_thing')
inject* methods are not being called.
There is a german blog entry explaining how it works.