Внедрить класс для просмотра компонента с помощью Hilt

У меня есть собственный WebView, который я добавляю в свой макет xml:

<my.company.ui.ExtendedWebView />

Он расширяет собственный WebView:

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

Как я могу использовать Hilt для внедрения класса @Singelton в класс выше? Инъекция собственности? Как я должен аннотировать класс?


person filur    schedule 28.09.2020    source источник


Ответы (2)


Я обнаружил, что аннотация @AndroidEntryPoint должна быть в представлении, во фрагменте (если во фрагменте) и в действии. Потому что Аннотации.

Итак, считайте, что ваш DI настроен следующим образом:

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

И мое приложение правильно настроено:

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

Теперь, если у меня есть представление с внедренной зависимостью:

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

Я получу ошибку:

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

Поэтому я добавил аннотацию @AndroidEntryPoint к фрагменту, содержащему представление:

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

И тогда мы получаем следующую ошибку:

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

Итак, я узнал, что аннотации должны подниматься вверх, от просмотра до (если во фрагменте) фрагмента, до действия:

@AndroidEntryPoint
class SuperAwesomeActivity : AppCompatActivity() {
...
person Quintin Balsdon    schedule 18.11.2020
comment
Ага, я пришел к такому же выводу. Принятие этого - person filur; 27.11.2020

Допустим, ваш singleton class в настоящее время выглядит так:

class ExampleSingletonClass( //... some dependencies) {
     //.. some other stuff
}

Чтобы сделать его синглтоном, измените его на:

@Singleton
class ExampleSingletonClass @Inject constructor( //... some dependencies) {
     //.. some other stuff
}

Затем, чтобы ввести его в свой ExtendedWebView, сделайте следующее:

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) {
// ...
}

Здесь вам не нужно @AndroidEntryPoint, но вашему Fragment / Activity нужно @AndroidEntryPoint

person Andrew    schedule 03.10.2020
comment
Спасибо. Если я это сделаю, я получу Types may only contain one @Inject constructor. Должен ли я удалить параметры по умолчанию? - person filur; 09.10.2020
comment
@filur Либо удалите параметр по умолчанию, либо создайте второй конструктор с параметром по умолчанию и пусть он указывает на первый конструктор. Сделайте @Inject и во втором конструкторе. Вы можете обратиться к этому - person Andrew; 09.10.2020
comment
Попался. Не могли бы вы опубликовать пример с подходом 2 конструктора? - person filur; 09.10.2020
comment
@filur Извините, но я видел, что это, к сожалению, невозможно (по крайней мере, как я пытался). Kotlin не может различить два конструктора только потому, что у одного есть значение по умолчанию, а у другого нет. Там написано Conflicting overloads. Мое решение: просто удалите параметры по умолчанию, если можете, а если нет, вам придется жить с предупреждением Types may only contain one @Inject constructor - person Andrew; 10.10.2020
comment
Спасибо, я полагаю, что в этом случае их удаление не повредит, поскольку, надеюсь, их устанавливает фреймворк. - person filur; 10.10.2020