gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 23:28:30 25 4
gpt4 key购买 nike

我关注了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


}

这是我的应用程序组件的一部分。然后在我的应用程序类上我这样做:

@Inject lateinit var myWorkerFactory: MyWorkerFactory

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

我的 Worker 类:

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

持有 worker 的类(class):

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

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

How is this even possible? I checked the implementation of RxWorker and it shouldn print at least the work itself until its started (i.e. someone subscribes to it)

2. 据推测,在您的开发过程中的某个时刻,您有工作人员在 ParcelListActivity.onCreate 方法中排队代码,并且您多次打开此 Activity ,因此使周期性工作人员多次排队次,WorkManager 将此工作持久化到其内部数据库中,现在该工作根据您之前的请求配置启动。

要解决此问题,您可以使用 cancelAllWork方法。但是正如文档声称的那样,应格外小心地使用此方法!通常周期性工作需要更精确的处理。例如你可以 assign a tag为您的工作要求,然后您可以使用 cancelAllWorkByTag取消工作的方法。此外你可以考虑launch your work as unique - 对于大多数情况,这是更合适的方法。

关于android - 即使没有安排 RxWorker 也被多次调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59641421/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com