简体   繁体   English

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

[英]Kotlin run coroutine during all app execution time

I am investigating and learning a bit about Kotlin coroutines .我正在调查和了解Kotlin coroutines My main thought is to try to create a function (coroutine) that is NOT running on main thread and is being executed all the time while the app is running.我的主要想法是尝试创建一个不在主线程上运行并且在应用程序运行时一直在执行的 function (协程)。 It shall be finished or killed when the app terminates.当应用程序终止时,它应该被完成或杀死。 This is like trying to run a background task, if I understood coroutines correctly.如果我正确理解协程,这就像尝试运行后台任务一样。

I made a first attempt to get this to work, and it seems like it actually works, but looks not optimal for me, I was wondering if there is a better way to do that:我第一次尝试让它工作,看起来它确实有效,但对我来说看起来不是最佳的,我想知道是否有更好的方法来做到这一点:

I basically just created a coroutine scope for the coroutine, and then simply used an infinite while loop for the coroutine...like this:我基本上只是为协程创建了一个协程 scope,然后简单地为协程使用了无限 while 循环......就像这样:

in my MainActivity.kt I have在我的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)
        }
    }

As I mentioned, this seems to work just fine...I can see the Log periodically being printed in logcat, and at the same time I can interact with the UI without any problem but...正如我所提到的,这似乎工作得很好......我可以看到日志定期打印在 logcat 中,同时我可以毫无问题地与 UI 交互,但是......

Is this the best optimal way to do this?这是做到这一点的最佳方式吗?

I would suggest delegating this off to a Worker to handle this task.我建议将其委托给 Worker 来处理此任务。 It isn't really your Activities responsibility to have really any knowledge of what this work is;真正了解这项工作的内容并不是您的活动责任; and if your activity gets destroyed / recreated, this work will start all over again.如果您的活动被破坏/重新创建,这项工作将重新开始。

Refer to: Android WorkManager and Coroutine Worker参考: Android WorkManagerCoroutine Worker

You could also make use of Androids LifecycleObserver to ensure this work only gets carried out when the application is in the foreground.您还可以使用 Android 的 LifecycleObserver 来确保仅当应用程序处于前台时才执行此工作。 Heres a quick sample for you:下面是一个快速示例:

Your Application Class您的应用 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
    }
}

Your Custom Worker您的定制工人

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()
        }
    }
}

MainActivity主要活动

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