所以我有一个处理网络请求的Android作业。
这项工作可以以多种方式启动,所以它可以轻松地运行parralel,这对我来说是不好的。我想实现这一点,作业不会启动两次,或者如果它启动了,那么在try catch块之前等待,直到第一次完成。
那么,我如何才能做到这一点,一次只运行一个对象。
我尝试添加TAG和setUpdateCurrent false,但它没有做任何事情,所以当我启动两次作业时,它并行运行。在那之后,我尝试了互斥锁和解锁。但它也做了同样的事情。
使用互斥锁,我应该创建一个原子互斥锁,并通过uniq标签或uuid调用锁?
好的,所以我找出了我的互斥锁有什么问题,作业每次都会创建一个新的互斥锁对象,所以它永远不会一样,也不会等待。
My Job:
class SendCertificatesJob @Inject constructor(
private val sendSync: SendSync,
private val sharedPreferences: SharedPreferences,
private val userLogger: UserLogger,
private val healthCheckApi: HealthCheckApi
) : Job(), CoroutineScope {
override val coroutineContext: CoroutineContext
get() = Dispatchers.IO
private val countDownLatch = CountDownLatch(1)
private val mutex = Mutex()
override fun onRunJob(params: Params): Result {
var jobResult = Result.SUCCESS
if (!CommonUtils.isApiEnabled(context))
return jobResult
val notificationHelper = NotificationHelper(context)
var nb: NotificationCompat.Builder? = null
if (!params.isPeriodic) {
nb = notificationHelper.defaultNotificationBuilder.apply {
setContentTitle(context.resources.getString(R.string.sending_certificates))
.setTicker(context.resources.getString(R.string.sending_certificates))
.setOngoing(true)
.setProgress(0, 0, true)
.setSmallIcon(android.R.drawable.stat_notify_sync)
.setLargeIcon(
BitmapFactory.decodeResource(
context.resources,
R.mipmap.ic_launcher
)
)
}
notificationHelper.notify(NOTIFICATION_ID, nb)
jobCallback?.jobStart()
}
val failureCount = params.failureCount
if (failureCount >= 3) {
nb?.setOngoing(false)
?.setContentTitle(context.resources.getString(R.string.sending_certificates_failed))
?.setTicker(context.resources.getString(R.string.sending_certificates_failed))
?.setProgress(100, 100, false)
?.setSmallIcon(android.R.drawable.stat_sys_warning)
notificationHelper.notify(NOTIFICATION_ID, nb)
return Result.FAILURE
}
GlobalScope.launch(Dispatchers.IO) {
mutex.lock()
userLogger.writeLogToFile("SendCertificatesJob.onRunJob(), date:" + Calendar.getInstance().time)
try {
//Test
var doIt = true
var count =0
while (doIt){
Timber.d("SendSyncWorker: $count")
count++
delay(10000)
if(count == 12)
doIt = false
}
healthCheckApi.checkHealth(ApiModule.API_KEY).await()
try {
sendSync.syncRecordedClients()
} catch (e: Exception) {
e.printStackTrace()
}
val result = sendSync().forEachParallel2()
result.firstOrNull { it.second != null }?.let { throw Exception(it.second) }
val sb = StringBuilder()
if (nb != null) {
nb.setOngoing(false)
.setContentTitle(context.resources.getString(R.string.sending_certificates_succeeded))
.setTicker(context.resources.getString(R.string.sending_certificates_succeeded))
.setProgress(100, 100, false)
.setStyle(NotificationCompat.BigTextStyle().bigText(sb.toString()))
.setSmallIcon(android.R.drawable.stat_notify_sync_noanim)
notificationHelper.notify(NOTIFICATION_ID, nb)
jobCallback?.jobEnd()
}
sharedPreferences.edit().putLong(KEY_LATEST_CERTIFICATES_SEND_DATE, Date().time)
.apply()
} catch (e: Exception) {
Timber.tag(TAG).e(e)
if (nb != null) {
nb.setOngoing(false)
.setContentTitle(context.resources.getString(R.string.sending_certificates_failed))
.setTicker(context.resources.getString(R.string.sending_certificates_failed))
.setProgress(100, 100, false)
.setSmallIcon(android.R.drawable.stat_sys_warning)
notificationHelper.notify(NOTIFICATION_ID, nb)
jobCallback?.jobEnd()
}
jobResult = Result.RESCHEDULE
} finally {
countDownLatch.countDown()
mutex.unlock()
}
}
countDownLatch.await()
return jobResult
}
Job schedule:
fun scheduleNowAsync(_jobCallback: JobCallback? = null) {
jobCallback = _jobCallback
JobRequest.Builder(TAG_NOW)
.setExecutionWindow(1, 1)
.setBackoffCriteria(30000, JobRequest.BackoffPolicy.LINEAR)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
.setRequirementsEnforced(true)
.setUpdateCurrent(true)
.build()
.scheduleAsync()
}
fun schedulePeriodicAsync() {
jobCallback = null
JobRequest.Builder(TAG)
.setPeriodic(900000)
.setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
.setRequirementsEnforced(true)
.setUpdateCurrent(true)
.build()
.scheduleAsync()
}发布于 2021-11-11 12:13:52
我找到了我的问题的解决方案。
因此,因为我使用dagger,所以我提供了一个单例互斥对象,并将其注入到作业中。当作业开始调用mutex.lock()时,因为互斥锁只有一个对象,所以即使另一个作业开始,第二个作业也会一直等到第一个作业完成。
https://stackoverflow.com/questions/69910320
复制相似问题