首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RxWorker被多次调用,即使在未计划的情况下?

RxWorker被多次调用,即使在未计划的情况下?
EN

Stack Overflow用户
提问于 2020-01-08 07:41:27
回答 1查看 637关注 0票数 3

我遵循了关于如何在WorkManagers上执行DI的文章,所以我有一个工厂:

代码语言:javascript
复制
 class MyWorkerFactory @Inject constructor(
        val workerFactories: Map<Class<out ListenableWorker>, @JvmSuppressWildcards Provider<ChildWorkerFactory>>
) : WorkerFactory() {

    override fun createWorker(
            appContext: Context,
            workerClassName: String,
            workerParameters: WorkerParameters
    ): ListenableWorker? {

        val foundEntry = workerFactories.entries.find { Class.forName(workerClassName).isAssignableFrom(it.key) }

        return if (foundEntry != null) {
            val factoryProvider = foundEntry.value
            factoryProvider.get().create(appContext, workerParameters)
        } else {
            val workerClass = Class.forName(workerClassName).asSubclass(ListenableWorker::class.java)
            val constructor = workerClass.getDeclaredConstructor(Context::class.java, WorkerParameters::class.java)
            constructor.newInstance(appContext, workerParameters)
        }

    }
}

这是我的模块:

代码语言:javascript
复制
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class WorkerKey(val value: KClass<out ListenableWorker>)


@Module
abstract class ParcelPollModule {

    @Binds
    @IntoMap
    @WorkerKey(ParcelPollWorker::class)
    internal abstract fun bindMyWorkerFactory(worker: ParcelPollWorker.Factory): ChildWorkerFactory


}

这是我的应用程序组件的一部分。然后,在我的应用程序类中,我执行以下操作:

代码语言:javascript
复制
@Inject lateinit var myWorkerFactory: MyWorkerFactory

private fun setupWorkerFactory() {
        WorkManager.initialize(
                this,
                Configuration.Builder()
                        .setWorkerFactory(myWorkerFactory)
                        .build()
        )
    }

我的工人阶级:

代码语言:javascript
复制
class ParcelPollWorker constructor(val parcelRepository: LocalParcelRepository,
                                   val correosRepository: CorreosRepository,
                                   appContext: Context, workerParams: WorkerParameters) : RxWorker(appContext, workerParams) {
    override fun createWork(): Single<Result> {
        Timber.w("Parcel poll worker $this here trying to do some work!")
        return parcelRepository.getParcels()
                .flatMapIterable {
                    it
                }

                .map {
                    Timber.d("Parcel poll checking parcel with code ${it.code}")
//                    correosRepository.getParcelStatus(it.code)
                }
                .toList()
                .map { Result.success() }
                .onErrorReturn {
                    Result.failure()
                }

    }


    class Factory @Inject constructor(
            val myRepository: LocalParcelRepository,
            val networkService: CorreosRepository
    ) : ChildWorkerFactory {

        override fun create(appContext: Context, params: WorkerParameters): ListenableWorker {
            return ParcelPollWorker(myRepository, networkService, appContext, params)
        }
    }


}

现在,即使我根本没有调度这个工作人员,我的日志也是用不同的实例多次打印Parcel poll worker $this here trying to do some work! (有时3,有时6)!此外,在启动应用程序时,实际工作的行会多次打印:

代码语言:javascript
复制
2020-01-08 08:37:40.892 7011-7011/com.myapp.android W/ParcelPollWorker: Parcel poll worker com.myapp.service.worker.ParcelPollWorker@c1f5d23 here trying to do some work!
2020-01-08 08:37:40.923 7011-7011/com.myapp.android W/ParcelPollWorker: Parcel poll worker com.myapp.service.worker.ParcelPollWorker@c80a87f here trying to do some work!
2020-01-08 08:37:40.924 7011-7011/com.myapp.android W/ParcelPollWorker: Parcel poll worker com.myapp.service.worker.ParcelPollWorker@85b9895 here trying to do some work!
2020-01-08 08:37:40.945 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583511008898301184149
2020-01-08 08:37:40.946 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 800692129
2020-01-08 08:37:40.946 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code PQ5HG70200028570115706M
2020-01-08 08:37:40.946 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code UX6CFH0459568380108027M
2020-01-08 08:37:40.947 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 6307253297994985
2020-01-08 08:37:40.949 7011-7113/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583560022440001250051
2020-01-08 08:37:40.954 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583511008898301184149
2020-01-08 08:37:40.955 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 800692129
2020-01-08 08:37:40.955 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code PQ5HG70200028570115706M
2020-01-08 08:37:40.955 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583511008898301184149
2020-01-08 08:37:40.955 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 800692129
2020-01-08 08:37:40.955 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code UX6CFH0459568380108027M
2020-01-08 08:37:40.955 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code PQ5HG70200028570115706M
2020-01-08 08:37:40.956 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code UX6CFH0459568380108027M
2020-01-08 08:37:40.956 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 6307253297994985
2020-01-08 08:37:40.956 7011-7102/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583560022440001250051
2020-01-08 08:37:40.956 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 6307253297994985
2020-01-08 08:37:40.956 7011-7101/com.myapp.android D/ParcelPollWorker$createWork: Parcel poll checking parcel with code 63583560022440001250051

这怎么可能?我检查了RxWorker的实现,它应该至少打印工作本身,直到它开始(即有人订阅它)

代码语言:javascript
复制
public RxWorker(@NonNull Context appContext, @NonNull WorkerParameters workerParams) {
    super(appContext, workerParams);
}

@NonNull
@Override
public ListenableFuture<Result> startWork() {
    mSingleFutureObserverAdapter = new SingleFutureAdapter<>();

    final Scheduler scheduler = getBackgroundScheduler();
    createWork()
            .subscribeOn(scheduler)
            // observe on WM's private thread
            .observeOn(Schedulers.from(getTaskExecutor().getBackgroundExecutor()))
            .subscribe(mSingleFutureObserverAdapter);
    return mSingleFutureObserverAdapter.mFuture;
}

我在这里迷失在可能发生的事情上。代码是开放源码的,可以检查这里

持有该工人的班级:

代码语言:javascript
复制
class ParcelListActivity : BaseActivity() {


    @Inject
    lateinit var myWorkerFactory: MyWorkerFactory


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayShowTitleEnabled(true)

        fab.setOnClickListener {
            startActivityForResult(CreateActivity.newIntent(this),
                    REQ_CREATE_PARCEL)
        }

        val constraints = Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build()


        val uploadWorker = PeriodicWorkRequest.Builder(
                ParcelPollWorker::class.java, 15, TimeUnit.MINUTES)
                .setConstraints(constraints)
                .build()
        WorkManager.getInstance(this).enqueue(uploadWorker)
    }

...

}

“艺术建议”之后的变化:

代码语言:javascript
复制
private fun initWorker() {
        val constraints = Constraints.Builder()
                .setRequiredNetworkType(NetworkType.CONNECTED)
                .build()


        val uploadWorker = PeriodicWorkRequest.Builder(
                ParcelPollWorker::class.java, 15, TimeUnit.MINUTES)
                .setConstraints(constraints)
                .build()
        WorkManager.getInstance(this).cancelAllWork()
        WorkManager.getInstance(this).enqueueUniquePeriodicWork(PARCEL_CHECKER_WORKREQUEST, ExistingPeriodicWorkPolicy.REPLACE, uploadWorker)

    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-17 09:17:31

1.注意到,根据RxWorker的源代码

代码语言:javascript
复制
@NonNull
@Override
public ListenableFuture<Result> startWork() {
    mSingleFutureObserverAdapter = new SingleFutureAdapter<>();

    final Scheduler scheduler = getBackgroundScheduler();
    createWork()
        .subscribeOn(scheduler)
        // observe on WM's private thread
        .observeOn(Schedulers.from(getTaskExecutor().getBackgroundExecutor()))
        .subscribe(mSingleFutureObserverAdapter);
    return mSingleFutureObserverAdapter.mFuture;
}

工作的执行是在调用subscribe对象的Single方法时开始的。所以你的说法是不正确的:

这怎么可能?我检查了RxWorker的实现,它应该至少打印工作本身,直到它开始(即有人订阅它)

2.大概是在您的开发过程中的某个时刻,您在ParcelListActivity.onCreate方法中使用了员工队列代码,并且您多次打开了该活动,因此多次对定期工作人员进行了排队,WorkManager将此工作保留在其内部数据库中,现在根据您的预请求配置启动该工作。

要解决这个问题,可以使用cancelAllWork方法。但是,正如docs声称的那样,这个方法应该非常谨慎地使用!一般情况下,定期工作需要更精确的处理。例如,您可以对工作请求进行指定一个标记,然后可以使用cancelAllWorkByTag方法取消工作。此外,您还可以考虑使用以独特的方式展开你的工作 --在大多数情况下,这是更合适的方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59641421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档