Table of contents
- The problem I am trying to solve
- When does injecting happen
- Proving it with code
- TLDR(Too Long Didn't Read)
My app on the Google Playstore
GitHub code
Introduction
- This series will be an informal demonstration of any problems I face or any observations I make while developing Android apps. Each blog post in this series will be unique and separate from the others, so feel free to look around.
The problem I am trying to solve
- So I have this piece of code that I need to interact with:
@AndroidEntryPoint
class BillingService: Service() {
@Inject lateinit var billingClientWrapper: BillingClientWrapper
}
- To interact with
billingClientWrapper
I need to be able to call this method:
billingClientWrapper.startBillingConnection(MutableLiveData(false))
- The problem is that I do not know when Hilt does field injecting. However, by the end of this blog post, both you and I will know when Hilt injects field injections.
When does the injecting take place?
When injecting into a Android Service, it is important that we use field injection. Mainly because the Android system takes care of the Service creation and does not allow use to parameters.
In order to use field injections Hilt must know how to create the class. If we own the class, we can simply annotate the classes constructor with
@Inject constructor
. However, if we do not own the class we must create the appropriate Hilt moduleI would also like to point out the fact that the Service is annotated with
@AndroidEntryPoint
. Not only is it required to use field injection but@AndroidEntryPoint
generates an individual Hilt component for each Android class in your project. Meaning that any class annotated with@AndroidEntryPoint
will get a specific hilt component generated with it.As the documentation states,
For each Android class in which you can perform field injection, there's an associated Hilt component
. If we can look at THIS documentation we can see theServiceComponent
(gets created for Service classes) is generated during the service onCreate() method.This all ultimately means that since we are using
@Inject
inside of a Service class that is annotated with@AndroidEntryPoint
this will happen:
1) Android system creates the Service
2) Service onCreate() method gets called
3) Hilt creates ServiceComponent
4) Hilt uses ServiceComponent to @Inject annotated fields
Proving it
- if you want to prove this yourself try the same code but with an init block, like so:
@AndroidEntryPoint
class BillingService: Service() {
@Inject lateinit var billingClientWrapper: BillingClientWrapper
init{
billingClientWrapper.startBillingConnection(MutableLiveData(false))
}
}
- The init{} block gets called upon initial creation of the
BillingService
and before the Service onCreate() method. if you run this code or try to interact with a field injection inside of a service before onCreate() runs the code will crash.
-To make this code run properly we must do this:
override fun onCreate() {
super.onCreate()
billingClientWrapper.startBillingConnection(MutableLiveData(false))
}
- Since @Inject is injected during onCreate() this code will run fine.
TLDR (Too long didn't read)
- Use THIS chart to tell when fields are being injected
Conclusion
- Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter.
Top comments (0)