首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何避免android Job并行运行?

如何避免android Job并行运行?
EN

Stack Overflow用户
提问于 2021-11-10 08:58:55
回答 1查看 31关注 0票数 0

所以我有一个处理网络请求的Android作业。

这项工作可以以多种方式启动,所以它可以轻松地运行parralel,这对我来说是不好的。我想实现这一点,作业不会启动两次,或者如果它启动了,那么在try catch块之前等待,直到第一次完成。

那么,我如何才能做到这一点,一次只运行一个对象。

我尝试添加TAG和setUpdateCurrent false,但它没有做任何事情,所以当我启动两次作业时,它并行运行。在那之后,我尝试了互斥锁和解锁。但它也做了同样的事情。

使用互斥锁,我应该创建一个原子互斥锁,并通过uniq标签或uuid调用锁?

好的,所以我找出了我的互斥锁有什么问题,作业每次都会创建一个新的互斥锁对象,所以它永远不会一样,也不会等待。

代码语言:javascript
复制
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()
        }
EN

回答 1

Stack Overflow用户

发布于 2021-11-11 12:13:52

我找到了我的问题的解决方案。

因此,因为我使用dagger,所以我提供了一个单例互斥对象,并将其注入到作业中。当作业开始调用mutex.lock()时,因为互斥锁只有一个对象,所以即使另一个作业开始,第二个作业也会一直等到第一个作业完成。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69910320

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档