DEV Community

Cover image for When does Hilt inject field injections
Tristan Elliott
Tristan Elliott

Posted on

When does Hilt inject field injections

Table of contents

  1. The problem I am trying to solve
  2. When does injecting happen
  3. Proving it with code
  4. 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

}

Enter fullscreen mode Exit fullscreen mode
  • To interact with billingClientWrapper I need to be able to call this method:
billingClientWrapper.startBillingConnection(MutableLiveData(false))
Enter fullscreen mode Exit fullscreen mode
  • 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 module

  • I 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 the ServiceComponent (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))
    }

}
Enter fullscreen mode Exit fullscreen mode
  • 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))

    }
Enter fullscreen mode Exit fullscreen mode
  • 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)