Внедрение репозитория в сервис в Android с помощью Hilt

У меня есть проект Android с внедрением зависимостей Hilt. Я определил MyApplication и MyModule следующим образом.

@HiltAndroidApp
class MyApplication : Application()

@Module
@InstallIn(ApplicationComponent::class)
abstract class MyModule {
    @Binds
    @Singleton
    abstract fun bindMyRepository(
        myRepositoryImpl: MyRepositoryImpl
    ): MyRepository
}

MyRepositoryImpl реализует интерфейс MyRepository:

interface MyRepository {
    fun doSomething(): String
}

class MyRepositoryImpl
@Inject
constructor(

) : MyRepository {
    override fun doSomething() = ""
}

Теперь я могу внедрить эту реализацию MyRepository в ViewModel:

class MyActivityViewModel
@ViewModelInject
constructor(
    private val myRepository: MyRepository,
) : ViewModel() { }

Это работает, как ожидалось. Однако, если я попытаюсь внедрить репозиторий в службу, я получаю сообщение об ошибке java.lang.Class<MyService> has no zero argument constructor:

class MyService
@Inject
constructor(
    private val myRepository: MyRepository,
): Service() { }

Та же ошибка возникает и с действием:

class MyActivity
@Inject
constructor(
    private val myRepository: MyRepository,
) : AppCompatActivity(R.layout.my_layout) { }

Что я делаю не так с уколом?


person MikkoP    schedule 06.09.2020    source источник
comment
Вы не можете использовать внедрение конструктора с Activity или Service. Используйте полевую инъекцию.   -  person Bek    schedule 07.09.2020


Ответы (3)


Из документации о том, как мы внедряем зависимости в классы Android , мы можем узнать следующее:

Hilt может предоставлять зависимости другим классам Android, имеющим аннотацию @AndroidEntryPoint.

В настоящее время Hilt поддерживает следующие классы Android:

  • Application (с использованием @HiltAndroidApp)
  • Activity
  • Fragment
  • View
  • Service
  • BroadcastReceiver

Поэтому, когда вы создаете подкласс любого из этих классов Android, вы не просите Hilt внедрять зависимости через конструкторы. Вместо этого вы аннотируете его с помощью @AndroidEntryPoint и просите Hilt внедрить его зависимости, аннотируя свойство с помощью @Inject:

@AndroidEntryPoint
class ExampleActivity : AppCompatActivity() { 

    @Inject
    lateinit var mAdapter: SomeAdapter 

    ...

}

Итак, в вашем случае вы должны ввести MyRepository в MyActivity и MyService следующим образом:

@AndroidEntryPoint
class MyService: Service() {

    @Inject
    lateinit var myRepository: MyRepository
   
    ...

}

@AndroidEntryPoint
class MyActivity: AppCompatActivity(R.layout.my_layout) { 

    @Inject
    lateinit var myRepository: MyRepository

    ...

}

И запомни:

Поля, введенные Hilt, не могут быть закрытыми

Вот и все, что касается классов Android, которые поддерживает Hilt.

Если вам интересно, а как насчет классов, не поддерживаемых Hilt (например: ContentProvider) ?! Я рекомендую изучить, как из этого руководства аннотация @EntryPoint в codelab (также не забудьте проверить документацию о том, как внедрять зависимости в классы не поддерживается Hilt).

person Ahmed Shendy    schedule 07.09.2020

Также, если вы переопределяете onCreate в своей службе - не забудьте добавить super.onCreate (), иначе вы получите исключение времени выполнения, что значение myRepository не может быть инициализировано (я некоторое время боролся с этой ошибкой во время рефакторинга моей службы, поэтому, возможно, это будет кому-то полезно)

@AndroidEntryPoint
class MyService : Service() {
    @Inject
    lateinit var myRepository: MyRepository

    override fun onCreate() {
        super.onCreate()

    }
}
person polis    schedule 20.04.2021
comment
Спасибо брат! Очень долго мучился в поисках ответа. Да, я удалил super () и получал эту ошибку - person Сергей; 01.06.2021

Вы используете @Inject в классе MyService, как если бы MyService вводили в какое-то другое место.

Если я правильно понял, вам нужно что-то более похожее на:

@AndroidEntryPoint
class MyService : Service() {

    @Inject
    lateinit var myRepository: MyRepository

}
person veritas1    schedule 06.09.2020