简体   繁体   English

Android如何使用Koin实现JobScheduler

[英]Android How to implement JobScheduler with Koin

I'm starting to use Koin as a service locator/DI due to it's simplicity to implement. 由于易于实现 ,我开始将Koin用作服务定位器/ DI。 I'm facing a issue regarding : Evernote Jobscheduler 我面临有关的一个问题: Evernote Jobscheduler

As of now I have the following code: 到目前为止,我有以下代码:

class ForceUpdateJob : Job() {
const val TAG: String = "FORCE_UPDATE_JOB_TAG"

 fun scheduleJob() {
//Code
}
override fun onRunJob(params: Params): Result {
//Code
}

On my SplashViewModel I call all my jobs like this: 在我的SplashViewModel上,我这样调用所有工作:

 private fun scheduleJobs() {
    if (JobManager.instance().getAllJobRequestsForTag(Sync1.TAG).isEmpty())
        Sync1.scheduleJob()

    if (JobManager.instance().getAllJobRequestsForTag(Sync2.TAG).isEmpty())
        Sync2.scheduleJob()

    if (JobManager.instance().getAllJobRequestsForTag(ForceUpdateJob.TAG).isEmpty())
        ForceUpdateJob.scheduleJob()
}

I have a job creator like this: 我有一个像这样的工作创造者:

class MyJobCreator : JobCreator {

override fun create(tag: String): Job? = when (tag) {
    Sync1Job.TAG -> Sync1Job()
    Sync2Job.TAG -> Sync2Job()
    ForceUpdateJob.TAG -> ForceUpdateJob()
    else -> null
}
}

And on my App class I create the JobManager like this: 然后在我的App类上创建JobManager,如下所示:

  JobManager.create(this).addJobCreator(MyJobCreator())

And it works perfectly, all my jobs are periodic and are scheduled every 15 minutes, everything runs and works fine. 它运行良好,我的所有工作都是定期的,每15分钟安排一次,一切运行正常。 (This structure follows the instructions on the Jobscheduler github page) (此结构遵循Jobscheduler github页面上的说明)

But when starting using DI with Koin, the following changes have been made: 但是,当开始在Koin中使用DI时,已进行了以下更改:

I have my module with all dependencies that I need: 我的模块具有我需要的所有依赖项:

val forceUpdateModule: Module = module {
bean { ForceUpdateDataSource() as ForceUpdateDataSourceInterface }
bean { ForceUpdateRepository(get()) as ForceUpdateRepositoryInterface }
factory { ForceUpdateWorker(get()) }
factory { ForceUpdateJob(get()) }
}

My Repository singleton instance is now passed by dependency for my Worker, and Worker is passed as a dependency for my update job: 现在,我的Repository单例实例通过我的Worker的依赖关系传递,而Worker作为我的更新作业的依赖关系传递:

class ForceUpdateJob(val forceUpdateWorker: ForceUpdateWorker) : Job() 

class ForceUpdateWorker(val repository: ForceUpdateRepositoryInterface)

So in order for this to work, I had to change my JobCreator class: 因此,为了使其正常工作,我必须更改JobCreator类:

class MyJobCreator(private val forceUpdateJob: ForceUpdateJob) : JobCreator

And create a new module for this: 并为此创建一个新模块:

val jobSchedulerModule: Module = applicationContext {
factory { MyJobCreator(get()) }
}

The weird part comes on the AppCoordinator, I created a property and injected it: 奇怪的部分出现在AppCoordinator上,我创建了一个属性并将其注入:

So this: 所以这:

 JobManager.create(this).addJobCreator(MyJobCreator())

Became this: 成为这样:

private val myJobCreator : MyJobCreator by inject()
JobManager.create(this).addJobCreator(myJobCreator)

And I start koin like this: 我像这样开始koin:

private fun initKoin() {
    startKoin(this,
            listOf(forceUpdateModule,
                    splashModule,
                    jobSchedulerModule))
}

And this indeed works for the first time. 这确实是第一次。 But when the job is rescheduled and tries to execute again, my app crashes with the following exception: 但是当重新安排作业并尝试再次执行时,我的应用程序崩溃,但出现以下异常:

Job for tag FORCE_UPDATE_TAG was already run, a creator should always create a new Job instance 标签FORCE_UPDATE_TAG的作业已经运行,创建者应始终创建一个新的Job实例

Any ideas on what am I missing? 关于我缺少什么的任何想法?

Thanks in advance 提前致谢

I think your problem has to do with the fact that the job creator doesn't create jobs anymore. 我认为您的问题与工作创建者不再创建工作有关。

The job creator must follow the factory design pattern, every time the you want to reschedule a job you must create a new instance of this job. 作业创建者必须遵循工厂设计模式,每次您要重新安排作业时,都必须创建该作业的新实例。 So your MyJobCreator should only receive the necessary dependencies to create the jobs. 因此,您的MyJobCreator应该只接收创建作业所需的依赖项。 Not the jobs themselfs. 不是工作本身。

So I would remove the koin factory of jobs, and make your MyJobCreator receive a factoryUpdateWorker and it would have a create method like this: 因此,我将删除作业的koin工厂,并使您的MyJobCreator收到factoryUpdateWorker,并且它将具有以下创建方法:

class MyJobCreator(val forceUpdateWorker: ForceUpdateWorker) : JobCreator

    override fun create(tag: String): Job? = when (tag) {
        Sync1Job.TAG -> Sync1Job()
        Sync2Job.TAG -> Sync2Job()
        ForceUpdateJob.TAG -> ForceUpdateJob(forceUpdateWorker)
        else -> null
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM