Search code examples
androiddagger-2dagger-hilt

Inject class in to view component with Hilt


I have a custom WebView that I add to my layout xml:

<my.company.ui.ExtendedWebView />

It extends the native WebView:

class ExtendedWebView @JvmOverloads constructor(context: Context, 
    attrs: AttributeSet? = null,  defStyle: Int = 0) 
    : WebView(context, attrs, defStyle) {
// ...
}

How can I use Hilt to inject a @Singelton class in to the class above? Property injection? How should I annotate the class?


Solution

  • What I have found is that the @AndroidEntryPoint annotation needs to be on the View, the Fragment (if in a Fragment) AND the Activity. Because Annotations.

    So consider you have your DI set up as follows:

    /* CONTENTS OF com.org.app.di/dependencyModule.kt */
    @Module
    @InstallIn(ViewComponent::class)
    object DependencyModule {
        @Provides
        fun provideDependency(@ApplicationContext context: Context): DependencyType
                = DependencyInstance(context)
    }
    

    And my Application is properly set up:

    @HiltAndroidApp
    class SuperAwesomeApplication : Application()
    /* Remember to reference this is the manifest file, under the name attricbute! */
    

    Now if I have a View with an injected dependency:

    @AndroidEntryPoint
    class SuperAwesomeView(context: Context, attrs: AttributeSet) : View(context, attrs) {
        @Inject
        lateinit var dependency: DependencyType
        ...
    

    I will get the error:

    ...
    Caused by: java.lang.IllegalStateException: class com.app.org.ui.view.SuperAwesomeView, Hilt view must be attached to an @AndroidEntryPoint Fragment or Activity.
    ...
    

    So I added the @AndroidEntryPoint annotation to the Fragment containing the View:

    @AndroidEntryPoint
    class SuperAwesomeFragment : Fragment() {
    ...
    

    And then we get hit with the next error:

     Caused by: java.lang.IllegalStateException: Hilt Fragments must be attached to an @AndroidEntryPoint Activity. Found: class com.org.ui.SuperAwesomeActivity
    

    And so I've learned the annotations need to bubble all the way up, from View to (if in a Fragment) Fragment, to Activity:

    @AndroidEntryPoint
    class SuperAwesomeActivity : AppCompatActivity() {
    ...