android - 使协程的一部分继续取消

标签 android kotlin kotlin-coroutines

我有一个可以保存大文件的文件管理类。文件管理器类是一个应用程序单例,因此它比我的 UI 类长。我的 Activity/Fragment 可以从协程调用文件管理器的 save 挂起函数,然后在 UI 中显示成功或失败。例如:

//In MyActivity:
private fun saveTheFile() = lifecycleScope.launch {
    try {
        myFileManager.saveBigFile()
        myTextView.text = "Successfully saved file"
    } catch (e: IOException) {
        myTextView.text = "Failed to save file"
    }
}

//In MyFileManager
suspend fun saveBigFile() {
    //Set up the parameters
    //...

    withContext(Dispatchers.IO) {
        //Save the file
        //...
    }
}

这种方法的问题是我不希望在 Activity 完成时中止保存操作。如果在 withContext block 开始之前 Activity 被销毁,或者如果 withContext block 中有任何挂起点,那么保存将不会完成,因为协程将被取消.

我想要发生的是文件总是被保存。如果 Activity 仍然存在,那么我们可以在完成时显示 UI 更新。

我认为一种方法可能是像这样从挂起函数启动一个新的 coroutineScope,但是当它的父作业被取消时,这个范围似乎仍然被取消了。

suspend fun saveBigFile() = coroutineScope {
    //...
}

我认为另一种选择可能是使它成为一个常规函数,在它完成时更新一些 LiveData。 Activity 可以观察结果的实时数据,并且由于 LiveData 在销毁生命周期观察者时会自动删除它们,因此 Activity 不会泄露给 FileManager。如果可以代替上面那样复杂的事情,我想避免这种模式。

//In MyActivity:
private fun saveTheFile() {
    val result = myFileManager.saveBigFile()
    result.observe(this@MyActivity) {
        myTextView.text = when (it) {
            true -> "Successfully saved file"
            else -> "Failed to save file"
        }
    }
}

//In MyFileManager
fun saveBigFile(): LiveData<Boolean> {
    //Set up the parameters
    //...
    val liveData = MutableLiveData<Boolean>()
    MainScope().launch {
        val success = withContext(Dispatchers.IO) {
            //Save the file
            //...
        }
        liveData.value = success
    }
    return liveData
}

最佳答案

您可以用NonCancellable 包装您不想取消的位。

// May cancel here.
withContext(Dispatchers.IO + NonCancellable) {
    // Will complete, even if cancelled.
}
// May cancel here.

关于android - 使协程的一部分继续取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60155439/

相关文章:

android - Activity 和线程处理

arrays - Kotlin JSONArray 到 MutableList<JSONObject>

android - 如何对LiveData转换进行单元测试

android - 暂停协程功能,直到收到结果,然后继续

mongodb - KMongo 查询从 Mongo Shell 产生不同的结果

android - 在 Android 手机主屏幕上检测触摸或滑动

android - 如何在 Ice Cream Sandwich 的通知栏上添加图片

android - 如何使用带有 API 23 的 adb 在系统级别禁用 android 设备/模拟器的动画?

oop - 安卓 : repository pattern what is the best solution to create an object?

Kotlin 协程 : what's the diffrence between using NonCancellable and a standalone new Job