Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/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协程运行阻塞时未按预期工作,无法阻塞for循环的执行_Kotlin_Kotlin Coroutines - Fatal编程技术网

Kotlin协程运行阻塞时未按预期工作,无法阻塞for循环的执行

Kotlin协程运行阻塞时未按预期工作,无法阻塞for循环的执行,kotlin,kotlin-coroutines,Kotlin,Kotlin Coroutines,在我的应用程序中,我正在执行两个for循环,但是那些for循环需要按顺序安排,以下是用例: 有两个for循环: 1-图像标签列表 2-文本标签列表 我想做的是在ImageSticksList之后,如果正确完成,那么只会执行TextSticksList 此处,imagesticker列表包含用于从glide加载图像的url路径,但如果这些图像具有高分辨率,则即使尚未从url加载图像,它最终也会使线程继续。为了解决这个问题,我们尝试在glideonready和full方法中添加阻塞调用,但这并没有任

在我的应用程序中,我正在执行两个for循环,但是那些for循环需要按顺序安排,以下是用例:

有两个for循环: 1-图像标签列表 2-文本标签列表

我想做的是在ImageSticksList之后,如果正确完成,那么只会执行TextSticksList

此处,imagesticker列表包含用于从glide加载图像的url路径,但如果这些图像具有高分辨率,则即使尚未从url加载图像,它最终也会使线程继续。为了解决这个问题,我们尝试在glideonready和full方法中添加阻塞调用,但这并没有任何帮助。我很困惑阻止呼叫是如何工作的。对此,我们将非常感谢您的帮助

下面是执行for循环的代码:

 runBlocking {
                            launch {
                                imagestickers.forEach {
                                    runBlocking {
                                        var image = it.path
                                        var x = it.x
                                        var y = it.y
                                        image!!.log()
                                        setimagestickers(image!!, x!!, y!!, it.width!!, it.height!!)
                                    }
                                }
                            }.join()
                            textstickers.forEach {
                                runBlocking {
                                    var text = it.text.toString()
                                    var color = it.color
                                    var font = it.font
                                    var size = it.size
                                    var x = it.x
                                    var y = it.y
                                    setTextSticker(text, Color.parseColor(color), size!!, x!!, y!!)
                                }
                            }
                        }
以下是我的两种主要计算方法:

 fun setimagestickers(path:String,x:Int,y:Int,w:Int,h:Int){

           Glide.with(this@NewStickerActivity).asBitmap().timeout(6000000).load(path).into(object : CustomTarget<Bitmap>() {
               override fun onLoadCleared(placeholder: Drawable?) {

               }

               override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                   var size: ViewGroup.LayoutParams
                   var bmp1 = resource
                   size = UiHelper.getHeightWidth(this@NewStickerActivity, (w).toInt(), (h).toInt())
                   var resizedBitmap = Bitmap.createScaledBitmap(bmp1, size.width, size.height, false)
                   var drawable = BitmapDrawable(resources, resizedBitmap)
                   var dsImageSticker = DrawableSticker(drawable)
                   dsImageSticker.setTag("ImageSticker")
                   var pm: List<Int>
                   if (density > 3.0) {
                       pm = UiHelper.getmargins(this@NewStickerActivity, (x).toInt(), (y).toInt())
                   } else {
                       pm = UiHelper.getmargins(this@NewStickerActivity, (x).toInt(), (y).toInt())
                   }
                   Log.i("Hmmm:", pm.get(0).toFloat().toString() + "::" + pm.get(1).toFloat().toString())

                   stickerView.addStickerAndSetMatrix1(
                           dsImageSticker,
                           pm.get(0).toFloat(),
                           pm.get(1).toFloat()
                   )

               }

           })
    }
   fun setTextSticker(text: String, color: Int,size: Int, x: Int, y: Int){
            val bmp1: Bitmap
            val drawable: Drawable
            var l: List<Int>
            if (density > 3.0) {
                l = UiHelper.getmargins(this@NewStickerActivity, (x).toInt(), (y * 1.07).toInt())
            } else {
                l = UiHelper.getmargins(this@NewStickerActivity, x.toInt(), y.toInt())
            }
            //var tf = Typeface.createFromFile(assets,"fonts/"+path)
            var tf = Typeface.createFromAsset(assets, "fonts/Myriad Pro Bold SemiExtended.ttf")
            bmp1 = createBitmapFromLayoutWithText(this@NewStickerActivity, size, text, color, 0f, tf, 0f, 0f, color, Gravity.LEFT)
            drawable = BitmapDrawable(resources, bmp1)
            var dsTextSticker = DrawableSticker(drawable)
            dsTextSticker.setTag("textSticker")
            Log.i("Hmmm:", l.get(0).toFloat().toString() + "::" + l.get(1).toFloat().toString())
            /*if (rotate) {
                stic.addStickerAndSetrotate(
                        dsTextSticker, rotationdegress,
                        l.get(0).toFloat(),
                        l.get(1).toFloat()
                )
            } else {*/
            stickerView.addStickerAndSetMatrix1(
                    dsTextSticker,
                    l.get(0).toFloat(),
                    l.get(1).toFloat())



    }
在那之后,在资源准备就绪的内部做了诀窍

Glide.with(this@NewStickerActivity).asBitmap().timeout(6000000).load(path).into(object : CustomTarget<Bitmap>() {
               override fun onLoadCleared(placeholder: Drawable?) {

               }

               override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                   var size: ViewGroup.LayoutParams
                   var bmp1 = resource
                   size = UiHelper.getHeightWidth(this@NewStickerActivity, (w).toInt(), (h).toInt())
                   var resizedBitmap = Bitmap.createScaledBitmap(bmp1, size.width, size.height, false)
                   var drawable = BitmapDrawable(resources, resizedBitmap)
                   var dsImageSticker = DrawableSticker(drawable)
                   dsImageSticker.setTag("ImageSticker")
                   var pm: List<Int>
                   if (density > 3.0) {
                       pm = UiHelper.getmargins(this@NewStickerActivity, (x).toInt(), (y).toInt())
                   } else {
                       pm = UiHelper.getmargins(this@NewStickerActivity, (x).toInt(), (y).toInt())
                   }
                   Log.i("Hmmm:", pm.get(0).toFloat().toString() + "::" + pm.get(1).toFloat().toString())

                   stickerView.addStickerAndSetMatrix1(
                           dsImageSticker,
                           pm.get(0).toFloat(),
                           pm.get(1).toFloat()
                   )
                i++
                if(i < imagestickers.size){
                    setimagestickers(imagestickers.get(i).path!!, imagestickers.get(i).x!!, imagestickers.get(i).y!!, imagestickers.get(i).width!!, imagestickers.get(i).height!!)
                }
                   else{
                    if(textstickers.isNullOrEmpty()){
                        loader!!.hide()
                    }
                    else {
                        setTextSticker(textstickers.get(j).text!!, Color.parseColor(textstickers.get(j).color), textstickers.get(j).size!!, textstickers.get(j).x!!, textstickers.get(j).y!!)
                    }
                    }
               }

           })

然而,我仍然想知道如何用协同程序而不是这种方法来解决这个问题

您的任何代码都不会从运行阻塞或启动的协同程序中受益

如果由于每个任务的长时间运行特性,您的目标只是并行处理每个图像类型对象,那么您可以执行以下操作:

fun main() {
    runBlocking {
        imagestickers.map {
            launch {
                var image = it.path
                var x = it.x
                var y = it.y
                image!!.log()
                setimagestickers(image!!, x!!, y!!, it.width!!, it.height!!)
            }
        }.joinAll()
        textstickers.map {
            launch {
                var text = it.text.toString()
                var color = it.color
                var font = it.font
                var size = it.size
                var x = it.x
                var y = it.y
                setTextSticker(text, Color.parseColor(color), size!!, x!!, y!!)
            }
        }.joinAll()
    }
}
为什么我删除了你正在做的一些事情:

您进行的嵌套运行阻塞调用没有执行任何操作`runBlocking意味着阻塞,直到该块中的内容完成为止。您的for循环不是异步的,并且将一直运行,直到它们完成为止。 你的第一次协同程序发布也没有做什么。您启动了它,然后立即调用join。这意味着您要启动一个协同程序,但在继续之前要立即等待它完成。 它的作用是:

我们不是循环,而是将每个图像对象映射到一个作业列表,以同时运行协同路由。 然后,我们等待每个列表中的每个作业完成,然后再继续下一个列表。
请注意:使用非阻塞IO看起来不会给代码带来任何好处,在这种情况下,这种并行性将限制在您拥有的线程数量上。无论是否使用协程,对映像的获取都将阻止它所在的线程,除非在获取映像时使用一个非阻塞库,该库正确地生成。基本上,在完成之前,您进行异步滑动调用,而不会挂起协程。您必须更改的第一件事是引入suspend fun getImageSticker:

现在,如果要并行化setimagestickers调用,请在循环中启动它们:

launch {
    imagestickers.map {
        launch {
            var image = it.path
            var x = it.x
            var y = it.y
            image!!.log()
            setimagestickers(image!!, x!!, y!!, it.width!!, it.height!!)
        }
    }.joinAll()
    textstickers.forEach {
        ...
    }
}

为什么你需要runBlocking内部的启动调用?我不需要它,我知道,但是runBlocking对我不起作用,所以我只是尝试一下join,但似乎没有帮助@如果你只是按顺序同步加载图像,它能工作吗?因为在本例中,显然您希望避免任何并行性,只需按顺序加载图像。可能是HTTP请求在完全加载过大的图像之前超时了吗?@9000检查我的更新问题否这在应用建议更改后不起作用文本标签列表在imagestickers列表完成之前仍在执行,我知道imagestickers列表被称为图像时为什么会发生这种情况加载glide最终需要时间,因为它是从服务器加载的,因此我们需要以某种方式将gilde代码添加到阻塞中,但运行阻塞并不是魔术。如果Glide异步运行某个东西,并且在调用它时没有实际执行fetch to completion,那么需要找到一种方法等待它完成。这是一个Glide library问题…在按照您所说的方式实施后,我的活动会冻结并停止响应。是的,这就是有多层问题的问题所发生的情况。我的回答解决了其中两个问题。您在其上下文之外显示了代码,但是如果您在UI线程上运行的函数中编写了runBlocking,那么它当然会阻止它。尝试用launch替换,但您还需要适当的协同路由作用域。在用主协同路由作用域替换运行阻塞后,工作非常好!!
suspend fun getSticker(path: String): Bitmap =
    suspendCancellableCoroutine { continuation -> Glide
        .with(this@NewStickerActivity)
        .asBitmap()
        .timeout(6000000)
        .load(path)
        .into(object : CustomTarget<Bitmap>() {
            override fun onResourceReady(resource: Bitmap, x: Transition<in Bitmap>?) {
                continuation.resume(resource)
            }
        })
    }
suspend fun setimagestickers(path: String, x: Int, y: Int, w: Int, h: Int) {
    val resource = getSticker(path)
    var size: ViewGroup.LayoutParams
    var bmp1 = resource
    size = UiHelper.getHeightWidth(this@NewStickerActivity, (w).toInt(), (h).toInt())
    var resizedBitmap = Bitmap.createScaledBitmap(bmp1, size.width, size.height, false)

}
launch {
    imagestickers.map {
        launch {
            var image = it.path
            var x = it.x
            var y = it.y
            image!!.log()
            setimagestickers(image!!, x!!, y!!, it.width!!, it.height!!)
        }
    }.joinAll()
    textstickers.forEach {
        ...
    }
}