最近我在使用WorkManager重新安排任务时遇到了问题。目前发现,当使用Okhttp发出请求并在AuthInterceptor上引发错误后,它会卡住,没有其他任务被启动。
这是管理工作计划的JobOrganizer
类的第一步。它链接了第一个作业队列。还有更多未粘贴在此处的作业,但主要区别是第一个链接作业不需要WiFi网络限制,而其他作业则需要。
object JobOrganizer {
const val WORK_INTERVAL: Long = 20
const val SCH_DATA_UPDATE_WORK_RESCHEDULE = "scheduled_data_update_work_reschedule"
const val SCH_DATA_UPDATE_WORK = "scheduled_data_update_work"
private val schDataUpdateJob: OneTimeWorkRequest
get() = OneTimeWorkRequestBuilder<SCHDataUpdateJob>()
.addTag(SCH_DATA_UPDATE_WORK)
.setConstraints(wifiConstraint)
.build()
val wifiConstraint: Constraints
get() = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresDeviceIdle(false)
.setRequiresBatteryNotLow(false)
.setRequiresCharging(false)
.setRequiresStorageNotLow(false)
.build()
fun getWorkInfos(context: Context, tag: String): LiveData<List<WorkInfo>> {
val workManager = WorkManager.getInstance(context)
return workManager.getWorkInfosByTagLiveData(tag)
}
private fun clearWorks(workManager: WorkManager) {
workManager.pruneWork()
}
private fun cancelSCHJobs(context: Context) {
val workManager = WorkManager.getInstance(context)
workManager.cancelAllWorkByTag(SCH_DATA_UPDATE_WORK )
clearWorks(workManager)
}
fun scheduleJobs(context: Context) {
cancelSCHJobs(context)
WorkManager.getInstance(context)
.beginWith(schTypesDownloadJob)
.then(schDownloadJob)
.then(schDataUpdateJob)
.then(schDataUploadJob)
.then(schCleanupJob)
.enqueue()
FirebaseAnalytics.getInstance(context).logEvent(AnalyticsEvents.Sync.SYNC_SCH_CONFIGURE_FORM_CLEANUP, Bundle())
}
}
AuthInterceptor类
class AuthInterceptor(private val context: Context?) : Interceptor {
@Throws(IOException::class)
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
if (context == null) {
return chain.proceed(originalRequest)
}
val auth = AuthRepository(context).getAuth()
if (auth.isNullOrEmpty()) {
return chain.proceed(originalRequest)
}
val version = String.format(
"%s: %s (build %s)",
BuildConfig.FLAVOR,
BuildConfig.VERSION_NAME,
BuildConfig.VERSION_CODE
)
val compressedRequest = originalRequest.newBuilder()
.header("Authorization", String.format("Bearer %s", auth[0].token))
.header("mobile-app-version", version)
.build()
return chain.proceed(compressedRequest)
}
}
更新工作会重新安排自己,并延迟30分钟。主要的try / catch用于处理AuthInterceptor错误。
class SCHDataUpdateJob(var context : Context, params : WorkerParameters) : Worker(context, params) {
override fun doWork(): Result {
FirebaseAnalytics.getInstance(context).logEvent(AnalyticsEvents.Sync.SYNC_SCH_UPDATE_START, Bundle())
var success = UPDElementTypesJob(context).doWork()
if (!success) {
FirebaseAnalytics.getInstance(context).logEvent(AnalyticsEvents.Sync.SYNC_UPD_ELEMENTTYPES_ERROR, Bundle())
Log.e("SYNC", "SCHDataUpdateJob UPDElementTypesJob error")
}
FirebaseAnalytics.getInstance(context).logEvent(AnalyticsEvents.Sync.SYNC_SCH_UPDATE_FINISH, Bundle())
val dataUpdateWorkRequest = OneTimeWorkRequestBuilder<SCHDataUpdateJob>()
.setInitialDelay(JobOrganizer.WORK_INTERVAL, TimeUnit.MINUTES)
.addTag(JobOrganizer.SCH_DATA_UPDATE_WORK)
.setConstraints(JobOrganizer.wifiConstraint)
.build()
WorkManager.getInstance(applicationContext)
.enqueue(dataUpdateWorkRequest)
Log.e("SYNC", "SCHDataUpdateJob finished")
return Result.success()
}
}
这是调用scheduleJobs()的片段。
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
mainView = inflater.inflate(R.layout.fragment_draft_list, container, false)
sync = mainView!!.findViewById(R.id.sync)
sync.onClick {
mFirebaseAnalytics!!.logEvent(AnalyticsEvents.UPDATE_BUTTON_CLICKED, Bundle())
if (!ConnectionUtils.isConnectedToWifi(activity!!.applicationContext)) {
showConnectivityDialog()
} else {
sync.visibility = View.GONE
doAsync {
JobOrganizer.scheduleJobs(context!!)
}
}
}
if (forceDownload) {
JobOrganizer.scheduleJobs(context!!)
}
return mainView!!
}
有时这个最后一个任务不会被安排或者不能运行。有什么线索吗?
谢谢。
scheduleJobs()
函数?你能否通过更新问题来展示给我们,以便我们可以找出答案? - Harry TimothyJobOrganizer.scheduleJobs(context!!)
和FirebaseAnalytics.getInstance(context)
(在JobOrganizer内部)处设置断点,然后进行调试,它们会被调用吗? - Harry TimothyResult.failure()
吗?如果是这样,其他的任务将不会运行。也许当AuthInterceptor
返回一个错误响应时,你确实放置了一个Result.failure()
。然而我不能确定,因为你没有分享发送请求的代码。 - Furkan YurdakulcancelSCHJobs
。此外,如果您想要重新安排作业以在30分钟后执行,请改用PeriodicRequestBuilder
而不是OneTimeUniqueRequestBuilder
并使用不同的标签。如果两个作业的标签相同,则可能无法按照您的期望进行替换。 - Furkan Yurdakul