Android 无法取消用viewModelScope启动的协同路由

Android 无法取消用viewModelScope启动的协同路由,android,kotlin,mvvm,kotlin-coroutines,android-viewmodel,Android,Kotlin,Mvvm,Kotlin Coroutines,Android Viewmodel,我正在kotlin的viewModel的init内部启动协同程序。 协同路由侦听循环中的数据,一切正常,但作为标题,我无法取消该协同路由(或者可能viewmodel没有调用cleared),因为socked保持连接 // viewmodel init { viewModelScope.launch { connector() } } override fun onCleared() { viewModelScope.cancel() super.

我正在kotlin的viewModel的init内部启动协同程序。 协同路由侦听循环中的数据,一切正常,但作为标题,我无法取消该协同路由(或者可能viewmodel没有调用cleared),因为socked保持连接

// viewmodel
init {
    viewModelScope.launch {
        connector()
    }
}

override fun onCleared() {
    viewModelScope.cancel()
    super.onCleared()
}

suspend fun connector() = withContext(Dispatchers.IO){
    //val socket : Socket
    try {
             // connect socket
             // listen in loop
    } catch (Exception e){//whocares}

已尝试在活动的backpressed上调用finish()(也尝试了一个片段)

这应该可以解决您的问题,将作业分配给一个变量,然后使用它来取消

    var job : Job? = null

    // viewmodel
    init {
        job = viewModelScope.launch {
            connector()
        }
    }

    override fun onCleared() {
        job?.cancel()
        super.onCleared()
    }

    suspend fun connector() = withContext(Dispatchers.IO){
        //val socket : Socket
        try {
                 // connect socket
                 // listen in loop
        } ca

协同程序中的取消必须是合作的。i、 e您的代码应该检查协同程序状态。 在套接字连接中,应选中
isActive
ensure reactive()
至少在继续之前调用任何回调时。
理想的解决方案是手动关闭套接字连接器,因为不能保证任何回调都会成功。将被调用。您也可以尝试使用
suspendCancelableCorroutine

循环是否检查是否取消了该Corroutine?取消在协同程序中是合作的。@Commonware如何检查?尝试使用“while(coroutineContext.isActive)”,没有帮助,但是,一旦Cleared被调用,例程取消是协作的。你需要在你的循环中检查
isActive
,或者如果套接字阻塞了线程,那么直接杀死它,协同程序就不会到达下一个循环。
isActive
应该可以工作,假设你真的在检查它的时候你认为是这样的。如果无限期地阻塞I/O,则在这些阻塞期间将不会进行检查。您可能会看到,它似乎具有对协同路由友好的TCP套接字I/O。尝试终止套接字时,它会到达catch块,但当重新启动活动时,它仍然卡在catch块内(协同路由仍处于活动状态)。尝试在catch块中调用[coroutineContext.]cancel,但仍处于活动状态,唯一杀死它的是当我强制停止(或从android studio再次点击run)时。我必须说,这是一个持久的协同路由。协同路由可以通过在作用域或作业上调用cancel()来实现