Dagger2: как разрешить jobservice?

Я пытаюсь обновить свое простое приложение для Android, чтобы использовать Dagger2. Думаю, мне удалось понять некоторые основы, и основные вещи (действия, модели представлений, помощники) создаются с помощью этого.

Но есть еще одна небольшая проблема: в приложении есть кнопка, при нажатии которой она должна планировать службу вакансий. Я могу реорганизовать свой сервис вакансий, чтобы его зависимости передавались через его конструктор, но как мне создать его экземпляр из своей деятельности? Другими словами, как мне заменить этот код:

    val serviceComponent = ComponentName(getApplication(), DbUpdaterJob::class.java)
    var jobInfo = JobInfo.Builder(DB_UPDATER_JOB_ID, serviceComponent)
            .setRequiredNetworkType(networkType)
            .setPersisted(true)
            .build()

    val scheduler = getApplication<Application>().getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
    val res = scheduler.schedule(jobInfo)

так что создание экземпляра отнесено к кинжалу?

Спасибо!

Служба никогда не может быть создана с помощью Dagger. Его экземпляр создается фреймворком. Он может ввести себя позже.

Gabe Sechan 13.09.2018 18:54

но разве нет ничего похожего на daggerappcompatactivity, чтобы упростить создание экземпляров внутренних зависимостей моего класса dbupdaterjob?

Luis Abreu 13.09.2018 19:02
2
2
965
2

Ответы 2

Вам необходимо определить провайдеров:

@Provides
fun provideServiceComponent(app: Application): ComponentName =
        ComponentName(app, DbUpdaterJob::class.java) // assuming you have only one ServiceComponent


@Provides
fun provideJobInfo(
        serviceComponent: ComponentName
): JobInfo =
        JobInfo.Builder(DB_UPDATER_JOB_ID)
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_NONE)
                .setPersisted(true)
                .build()
@Provides
@Singleton
fun provideJobScheduler(app: Application): JobScheduler = app.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler

а затем ввести

@Inject constructor(
        jobInfo: JobInfo,
        scheduler: JobScheduler
) {
    val res = scheduler.schedule(jobInfo)
            ...
}

Это усложняется, если вы хотите иметь возможность создавать разные ComponentName или JobInfo и т. д. В этом случае вам нужно использовать инъекции @Named.

Я написал это здесь, но не смог скомпилировать, поэтому надеюсь, что не сделал ошибок

kingston 13.09.2018 19:03

ах, теперь я прочитал, что вы хотите сделать это на занятии. Мне это не кажется правильным, но в любом случае вам нужно ввести поля вместо параметров

kingston 13.09.2018 19:07

Моя проблема здесь в том, что я изменил свой JobService так, чтобы он получал другую зависимость через свой конструктор. Я могу сделать то, что сказал, но в конечном итоге получу то же исполнение ... Я думаю, что мне нужно передать ссылку через свойство (вместо того, чтобы вводить зависимость через конструктор, что имело больше смысла )

Luis Abreu 14.09.2018 10:30

После некоторого покопания это оказалось проще, чем я думал ... Итак, я создал новый модуль для привязки моей работы:

@Module
abstract class JobBindingModule {
    @ServiceScoped
    @ContributesAndroidInjector
    internal abstract fun provideDbUpdatedJob(): DbUpdaterJob
}

Кстати, ServiceScoped - это новая аннотация, которая выглядит так:

@Scope
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE, ElementType.METHOD)
annotation class ServiceScoped

Я добавил модуль в свою коллекцию модулей компонентов кинжала. После этого я заменил инъекцию параметров конструктора на инъекцию свойств:

class DbUpdaterJob: JobService() {
    @Inject
    lateinit var dbManager: NewsManager

И, наконец, я переопределил метод onCreate, чтобы ввести необходимые зависимости:

override fun onCreate() {
    super.onCreate()
    AndroidInjection.inject(this)
}

И вроде работает ...

Другие вопросы по теме