我已经关注this文章,该文章关于如何在WorkManagers上进行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)
}
最佳答案
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-在大多数情况下它是更合适的方法。