繁体   English   中英

Kotlin 在所有应用程序执行期间运行协程

[英]Kotlin run coroutine during all app execution time

我正在调查和了解Kotlin coroutines 我的主要想法是尝试创建一个不在主线程上运行并且在应用程序运行时一直在执行的 function (协程)。 当应用程序终止时,它应该被完成或杀死。 如果我正确理解协程,这就像尝试运行后台任务一样。

我第一次尝试让它工作,看起来它确实有效,但对我来说看起来不是最佳的,我想知道是否有更好的方法来做到这一点:

我基本上只是为协程创建了一个协程 scope,然后简单地为协程使用了无限 while 循环......就像这样:

在我的MainActivity.kt我有

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        CoroutineScope(Default).launch {
            runContinuousFunction()
        }
}

private suspend fun runContinuousFunction(){
        while (true){
            Log.d("debug", "Running continuous function")
            delay(2000)
        }
    }

正如我所提到的,这似乎工作得很好......我可以看到日志定期打印在 logcat 中,同时我可以毫无问题地与 UI 交互,但是......

这是做到这一点的最佳方式吗?

我建议将其委托给 Worker 来处理此任务。 真正了解这项工作的内容并不是您的活动责任; 如果您的活动被破坏/重新创建,这项工作将重新开始。

参考: Android WorkManagerCoroutine Worker

您还可以使用 Android 的 LifecycleObserver 来确保仅当应用程序处于前台时才执行此工作。 下面是一个快速示例:

您的应用 Class

class MyApp: Application(), LifecycleObserver {

    companion object {
        private var isAppForeground = true

        @Synchronized
        fun isAppInForeground(): Boolean = isAppForeground
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    private fun onAppBackground() {
        // Each time our app goes into the background this function 
        // will be called. Set the static boolean variable to false.
        isAppForeground = false
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private fun onAppForeground() {
        // Each time our app comes into the foreground this function 
        // will be called. Set the static boolean variable to true.
        isAppForeground = true
    }
}

您的定制工人

class MyWorker(
    context: Context, 
    workerParams: WorkerParameters
) : CoroutineWorker(context, workerParams) {

    companion object {
        const val WORK_TAG = "MyWorkerTag"
    }

    override suspend fun doWork(): Result {
        if (MyApp.isAppInForeground) {
        // Do your work here that you want to repeat.
        // You can return either Result.success()
        // Result.failure()
        // of Result.retry() if you want to retry this specific instance.
        } else {
            return Result.failure()
        }
    }
}

主要活动

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        initWorker()
}

private fun initWorker() {
    val workManager = WorkManager.getInstance(this)

    /* You can define whatever constraints are required for this
    work to run. Here I have just set a constraint that the device
    must have a valid network connection. Useful if your work will
    require API calls or upload / downloading data */
    val constraints = Constraints.Builder()
        .setRequiredNetworkType(NetworkType.CONNECTED)
        .build()

    /* Work can be scheduled on whatever repeating interval you define, with a
    minimum being every 15 minutes. */
    val myWorkRequest = PeriodicWorkRequestBuilder<MyWorker>(
            repeatInterval = 15L,
            repeatIntervalTimeUnit = TimeUnit.MINUTES
        ).setConstraints(constraints).build()

    /* You can define the existing work policy when enqueueing the work, to determine
    what will happen the next time this code is run. You can either REPLACE 
    the existing scheduled work or KEEP the existing work. */
    workManager.enqueueUniquePeriodicWork(
        MyWorker.WORK_TAG,
        ExistingPeriodicWorkPolicy.REPLACE,
        myWorkRequest
    )
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM