RxWorker即使没有安排也被多次调用?

问题描述 投票:3回答:1

我已经关注this关于如何在WorkManager上进行DI的文章,所以我有这个工厂:

 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)
        }

    }
}

这是我的模块:

@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


}

这是我的应用程序组件的一部分。然后在我的Application类上执行此操作:

@Inject lateinit var myWorkerFactory: MyWorkerFactory

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

我的工人班:

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)!在启动应用程序时,实际工作中的行也会多次打印:

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的实现,并且它不应至少打印工作本身,直到它开始(即有人订阅了它)]

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;
}

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

持有工人的班级:

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)
    }

...

}

[@ art建议后的更改:

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)

    }
android rx-java2 android-workmanager
1个回答
0
投票

1。请注意,根据RxWorker的源代码:

@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方法。但正如文档声称您使用此方法时,应格外小心!通常,定期工作需要更精确的处理。例如,您可以将assign a tag用于您的工作请求,然后可以使用cancelAllWorkByTag方法来取消工作。此外,您可以考虑launch your work as unique-对于大多数情况,它是更合适的方法。

© www.soinside.com 2019 - 2024. All rights reserved.