Reputation: 1556
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?
Upvotes: 5
Views: 8063
Reputation: 5881
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() {
...
Upvotes: 11
Reputation: 4712
Let's say your singleton class
currently looks like this:
class ExampleSingletonClass( //... some dependencies) {
//.. some other stuff
}
To make it a Singleton change it to:
@Singleton
class ExampleSingletonClass @Inject constructor( //... some dependencies) {
//.. some other stuff
}
Then, to inject it into your ExtendedWebView
do this:
class ExtendedWebView @JvmOverloads @Inject constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
private val exampleSingleton: ExampleSingletonClass // your singleton, doesn't need to be private.
) : WebView(context, attrs, defStyle) {
// ...
}
You don't need any @AndroidEntryPoint
here, but your Fragment / Activity
needs @AndroidEntryPoint
Upvotes: 2