Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Kotlin在所有应用程序执行期间运行协同程序_Kotlin_Kotlin Coroutines - Fatal编程技术网

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

Kotlin在所有应用程序执行期间运行协同程序,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,我正在调查和学习一点关于Kotlin合作项目的知识。我的主要想法是尝试创建一个不在主线程上运行并且在应用程序运行时一直在执行的函数(协同程序)。当应用程序终止时,它将被完成或终止。如果我正确理解协同程序,这就像尝试运行后台任务一样 我第一次尝试让它工作,它看起来确实有效,但对我来说似乎不是最优的,我想知道是否有更好的方法来做到这一点: 我基本上只是为协程创建了一个协程作用域,然后简单地为协程使用了一个无限while循环……如下所示: 在我的main活动中.kt我有 override fun on

我正在调查和学习一点关于Kotlin合作项目的知识。我的主要想法是尝试创建一个不在主线程上运行并且在应用程序运行时一直在执行的函数(协同程序)。当应用程序终止时,它将被完成或终止。如果我正确理解协同程序,这就像尝试运行后台任务一样

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

我基本上只是为协程创建了一个协程作用域,然后简单地为协程使用了一个无限while循环……如下所示:

在我的main活动中.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进行交互,没有任何问题,但是


这是最好的方法吗?

我建议将此任务委托给一名员工来完成。真正了解这项工作并不是你的责任;如果您的活动被破坏/重新创建,这项工作将重新开始

参考: 及

您还可以使用Androids LifecycleObserver来确保这项工作仅在应用程序处于前台时执行。这是给你的一个快速样本:

您的应用程序类

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()
        }
    }
}
main活动

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
    )
}
override-fun-onCreate(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
initWorker()
}
私人娱乐工作者(){
val workManager=workManager.getInstance(此)
/*您可以为此定义所需的任何约束
要运行的工作。在这里,我刚刚设置了一个约束,该设备
必须有一个有效的网络连接。如果您的工作需要,这将非常有用
需要API调用或上载/下载数据*/
val constraints=constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
/*您可以使用
至少每15分钟一次*/
val myWorkRequest=PeriodicWorkRequestBuilder(
重复间隔=15L,
repeatIntervalTimeUnit=TimeUnit.MINUTES
).setConstraints(constraints).build()
/*您可以在工作排队时定义现有工作策略,以确定
下次运行此代码时将发生什么。您可以替换
现有计划工作或保留现有工作*/
workManager.enqueueUniquePeriodicWork(
MyWorker.WORK_标签,
现有PeriodicWorkPolicy.REPLACE,
我的工作请求
)
}