簡體   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