我只是从Kotlin
协程开始。我正在尝试使用协程轮询服务器,并希望在Activity
或Fragment
暂停时停止轮询,并相应地恢复轮询。因此,我pollScope
的生命周期比所提供的生命周期短ViewModel.viewModelScope
。我对目前的实施方式不完全满意,有几个问题:
这是正确的创建方法吗pollScope
?我也希望它在取消时viewModelScope
也取消,这就是为什么我要指定父级作业。
onResume()
如果我取消pollJobs
使用,为什么协程不能开始coroutineContext.cancel()
?如果我保留一份工作清单并取消它们,它们会很好地启动。
这是整体正确的方法吗?有没有更好的办法?
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spruce.messenger.utils.FullLifecycleObserverAdapter import kotlinx.coroutines.* import java.io.IOException import java.util.concurrent.CopyOnWriteArrayList import kotlin.coroutines.CoroutineContext suspend fun poll(initialDelay: LOng= 5000, maxDelay: LOng= 30000, factor: Double = 2.0, block: suspend () -> Unit) { var currentDelay = initialDelay while (true) { try { try { block() currentDelay = initialDelay } catch (e: IOException) { currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelay) } delay(currentDelay) yield() } catch (e: CancellationException) { break } } } class MyDataModel : ViewModel() { val pollScope = CloseableCoroutineScope(SupervisorJob(parent = viewModelScope.coroutineContext[Job]) + Dispatchers.Main) private val pollJobs = CopyOnWriteArrayList() inner class CloseableCoroutineScope(context: CoroutineContext) : FullLifecycleObserverAdapter(), CoroutineScope { override val coroutineContext: CoroutineCOntext= context override fun onPause(owner: LifecycleOwner) { super.onPause(owner) // coroutineContext.cancel() // this cancels it but then coroutine doesn't start again in onResume() pollJobs.forEach { it.cancel() } } override fun onResume(owner: LifecycleOwner) { super.onResume(owner) refresh() } } fun refresh() { if (pollJobs.count { it.isActive } == 0) { startPoll() } } private fun startPoll() = pollScope.launch { try { poll { //fetch data from server } } catch (e: Exception) { //ignore } }.also { track(it) } private fun track(job: Job) { pollJobs.add(job) job.invokeOnCompletion { pollJobs.remove(job) } } }
然后在我的片段中,将pollScope添加为生命周期观察器viewLifecycleOwner.lifecycle.addObserver(viewModel.pollScope)
。