gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 13:19:27 25 4
gpt4 key购买 nike

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

有两个 for 循环:1-图像贴纸列表2-TextStickers列表

我想要做的是在 imagestickerslist 之后,如果正确完成,那么 textstickerslist 才会被执行。

这里的 imagesticker 列表由 url 路径组成,用于从 glide 加载图像,但是如果这些图像具有高分辨率,即使图像尚未从 url 加载,它最终也会使线程继续。为了解决这个问题,尝试添加阻塞调用以在ready和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())



}

更新:

我通过按顺序递增和获取图像来在没有协程的情况下完成此工作:首先,我获取了一个 Int,然后不断递增,直到达到列表大小,这是我的代码:首先我这样做了:

var i = 0 
setimagestickers(imagestickers.get(i).path!!, imagestickers.get(i).x!!, imagestickers.get(i).y!!, imagestickers.get(i).width!!, imagestickers.get(i).height!!)

在资源准备好之后,就成功了!!

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!!)
}
}
}

})

但是我仍然想知道如何使用协程而不是这种方法来解决它!

最佳答案

基本上,您在进行异步 Glide 调用时不会暂停协程,直到它们完成为止。您必须更改的第一件事是引入一个挂起函数 getImageSticker():

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)

}

现在,如果您想并行化 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 {
...
}
}

关于Kotlin 协程运行阻塞未按预期工作并且无法阻止 for 循环的执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59834331/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com