kotlin - 您应该将 coroutineScope 作为函数参数传递吗?

标签 kotlin kotlin-coroutines android-mvvm kotlin-coroutines-flow

我正在试验协程,但不确定是否将 coroutineScope 传递给普通的 Kotlin 用例。这种方法会造成内存泄漏吗?

假设我们在 VM 中初始化我们的 UseCase 并尝试传递 viewModelScope:

class UploadUseCase(private val imagesPreparingForUploadUseCase: ImagesPreparingForUploadUseCase){

fun execute(coroutineScope: CoroutineScope, bitmap: Bitmap) {
        coroutineScope.launch {
            val resizedBitmap = withContext(Dispatchers.IO) {
                imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
            }
        }
    }

}

是安全码吗?如果我在 VM 中声明这个确切的代码没有区别吗?如果不是,那意味着我可以将 coroutineScope 作为构造函数参数传递......现在我最初认为我应该通过以下方式创建我的 execute 方法:
fun CoroutineScope.execute(bitmap: Bitmap) {
        launch {
            val resizedBitmap = withContext(Dispatchers.IO) {
                imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
            }
        }
    }

}

据我所知,我们使用扩展函数来让方法使用 父协程范围。 这意味着,我不需要将 coroutineScope 作为参数传递,只需更改方法即可使用扩展函数。

但是,令我惊讶的是,VM 看不到此方法可用!为什么这个方法不能从VM调用?

这在 VM 中标记为红色:
 private fun uploadPhoto(bitmap: Bitmap, isImageUploaded: Boolean) {
        prepareDataForUploadingUseCase.execute(bitmap)
    }

这在 VM 中未标记为红色:
 private fun uploadPhoto(bitmap: Bitmap, isImageUploaded: Boolean) {
        prepareDataForUploadingUseCase.execute(viewModelScope, bitmap)
    }

如果我的理解是错误的,我为什么要用 CoroutineScope 作为扩展函数 而不是将 coroutineScope 作为函数参数传递 ?

最佳答案

将其作为参数传递与将其用作扩展函数接收器在最终结果中实际上是相同的。扩展函数接收器基本上是您传递给函数的另一个参数,只是为了方便起见重新排列了语法。所以你不能使用扩展函数作为“作弊”来避免通过接收器。

但无论哪种方式,我都认为这是一种笨拙的设计,必须提供一个范围,然后将协程设置隐藏在函数中。这导致在函数屏障的两侧传播协程范围操作。调用这个函数的函数必须知道一些协程将在它传递的作用域上被调用,但它不知道它是否需要担心如何处理取消以及它允许​​对这个作用域做什么它通过了。

在我看来,这样做会更清洁:

suspend fun execute(bitmap: Bitmap) = withContext(Dispatchers.IO) {
        imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
    }

所以调用函数可以在一个地方启动协程并处理整个协程。或者不传递协程范围,但具有 execute函数在内部生成自己的作用域(依赖于 lifecycleScopeviewModelScope,如果适用),并处理自己的取消行为。下面是创建生命周期作用域的子作用域并将其添加到在某些情况下您可能想要取消的某些作业集合的示例。
fun execute(bitmap: Bitmap) {
    lifecycleScope.launch {
        bitmapScopes += coroutineScope(Dispatchers.IO) {
            imagesPreparingForUploadUseCase.getResizedBitmap(bitmap, MAX_SIZE)
        }
    }
}

关于kotlin - 您应该将 coroutineScope 作为函数参数传递吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61606630/

相关文章:

android - Push Kit 什么时候会包含 android :exported attributes required for Android 12?

android - 在后续的挂起方法调用之间发出 LiveData 以更新 UI

android - recyclerview 上没有显示数据

android - 在 Activity/Fragment 中调用多个挂起函数

android - 如何摆脱这个 token 验证器 Hilt 依赖循环?

kotlin - 在流的收集中获取当前和以前的值

android - 在 Android 上重构 Observer

android - 使用 MVVM 架构的 Activity 共享元素转换

kotlin自定义从mutableList获取不可变列表

android - 让暂停功能不返回任何东西