Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/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
Android 与“碰撞”;尝试使用回收的位图“;使用Glide4.11,转换会导致这种情况吗?_Android_Kotlin - Fatal编程技术网

Android 与“碰撞”;尝试使用回收的位图“;使用Glide4.11,转换会导致这种情况吗?

Android 与“碰撞”;尝试使用回收的位图“;使用Glide4.11,转换会导致这种情况吗?,android,kotlin,Android,Kotlin,我知道已经有很多问题与“尝试使用回收的位图”崩溃有关,但没有一个对我有帮助 详情: 此项目中的任何位置都没有对Bitmap.recycle()的调用 使用Glide(4.11.0)加载所有图像 Glide调用都很简单,不使用占位符 在切换片段时,崩溃似乎是随机发生的 我唯一能想到的就是这些转变。 此项目中只有2个转换 CircletTransformation(将图像剪辑为具有自定义半径的圆): 和ClipWhiteTransformation(从图像中删除白色边框): 类ClipHiteT

我知道已经有很多问题与“尝试使用回收的位图”崩溃有关,但没有一个对我有帮助

详情:

  • 此项目中的任何位置都没有对Bitmap.recycle()的调用
  • 使用Glide(4.11.0)加载所有图像
  • Glide调用都很简单,不使用占位符
  • 在切换片段时,崩溃似乎是随机发生的
我唯一能想到的就是这些转变。 此项目中只有2个转换

CircletTransformation(将图像剪辑为具有自定义半径的圆):

和ClipWhiteTransformation(从图像中删除白色边框):

类ClipHiteTransformation():BitmapTransformation(){
伴星{
private const val ID=“com.project.transformation.clipWhite”
私有值ID_字节:ByteArray=ID.toByteArray()
//配置
const val white=253//白色像素,如果所有通道都等于或大于此值
const val transparent=50//透明像素,如果小于此值
}
公共覆盖乐趣转换(池:BitmapPool,源:位图,向外宽:Int,向外高:Int):位图{
val width=source.width-1
val高度=source.height-1
val halfX=宽度/2
val halfY=高度/2
var startY=0
//左边缘
左变量=0
用于(0中的x直到半x){
val pixel=source.getPixel(x,halfY)
//透明的?
如果(颜色alpha(像素)<透明)继续
//不是白人?
if(Color.red(像素)2){
startY=2
}
打破
}
}
//右边距
var right=0
用于(0中的x直到半x){
val pixel=source.getPixel(宽度-x,半像素)
//透明的?
如果(颜色alpha(像素)<透明)继续
//不是白人?
if(Color.red(像素)2){
startY=2
}
打破
}
}
//上边距
var top=0
对于(从星形到半星形){
val pixel=source.getPixel(halfX,y)
//透明的?
如果(颜色alpha(像素)<透明)继续
//不是白人?
if(Color.red(像素)abs(newHeight-outHeight))outWidth/newWidth.toFloat()其他outHeight/newHeight.toFloat()值
val矩阵=矩阵()。应用{setScale(scale,scale)}
返回Bitmap.createBitmap(源、左、上、新宽度、新高度、矩阵、假)
}
//缓存帮助程序
覆盖乐趣等于(其他:任何?):布尔值{
返回other is ClipWhiteTransformation&&other.hashCode()==hashCode()
}
重写哈希代码():Int{
返回ID.hashCode()
}
重写fun updateDiskCacheKey(messageDigest:messageDigest){
messageDigest.update(ID_字节)
}
}
最初使用BitmapPool时,删除它并没有阻止崩溃

顺便说一下,这是用于加载图像的扩展:

fun ImageView.setURL(url: String, 
                     @DrawableRes error: Int? = null, 
                     @DrawableRes placeholder: Int? = null, 
                     size: Int? = null, 
                     options: ((RequestBuilder<Drawable>) -> Unit)? = null, 
                     completion: ((resource: Drawable?) -> Unit)? = null) {

    // No URL, use Placeholder if exists, if not, use the error image
    if (url.isEmpty()) {
        placeholder?.also{ setImageResource(it) } ?: run { error?.also{ setImageResource(it) } }
        return
    }

    Glide.with(applicationInstance) // (I'm using an application instance directly here)
        .load(url).apply {
            completion?.also { completion ->
                this.listener(object : RequestListener<Drawable> {
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        completion(null)
                        return false
                    }
                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        completion(resource)
                        return false
                    }
                })
            }
        }
        .apply { size?.also { this.override(it)} }
        .apply { options?.invoke(this) }
        .placeholder(placeholder ?: 0)
        .error(error ?: 0)
        .transition(DrawableTransitionOptions.withCrossFade(350))
        .into(this)
}
fun ImageView.setURL(url:String,
@DrawableRes错误:Int?=null,
@DrawableRes占位符:Int?=null,
大小:Int?=null,
选项:((RequestBuilder)->Unit)?=null,
完成:((资源:可提取?->单位)?=null){
//没有URL,请使用占位符(如果存在),如果没有,请使用错误图像
if(url.isEmpty()){
占位符?.allow{setImageResource(it)}?:运行{error?.allow{setImageResource(it)}
返回
}
with(applicationInstance)//(我在这里直接使用一个应用程序实例)
.load(url).应用{
完成?也是{完成->
this.listener(对象:RequestListener{
重写fun onLoadFailed(e:GlideException?,model:Any?,target:target?,isFirstResource:Boolean):布尔{
完成(空)
返回错误
}
覆盖onResourceReady(资源:可绘制?、模型:任意?、目标:目标?、数据源:数据源?、isFirstResource:Boolean):布尔{
完成(资源)
返回错误
}
})
}
}
.apply{size?。同时{this.override(it)}
.apply{options?.invoke(this)}
.占位符(占位符?:0)
.错误(错误?:0)
.过渡(可绘制过渡选项,带交叉渐变(350))
.进入(这个)
}
很抱歉在这里粘贴了这么多代码(希望对其他人有用)。 这些变换或加载程序会导致崩溃吗?

塑造
(圆形/方形/椭圆形)
你不喜欢的图像
class ClipWhiteTransformation() : BitmapTransformation() {
    companion object {
        private const val ID = "com.project.transformation.clipWhite"
        private val ID_BYTES: ByteArray = ID.toByteArray()

        // Config
        const val white = 253       // White pixel, if all channels are equal or greater than this
        const val transparent = 50  // Transparent pixel, if Less than this
    }

    public override fun transform(pool: BitmapPool, source: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
        val width = source.width - 1
        val height = source.height - 1
        val halfX = width / 2
        val halfY = height / 2
        var startY = 0


        // Left Margin
        var left = 0
        for (x in 0 until halfX) {
            val pixel = source.getPixel(x, halfY)

            // Transparent?
            if (Color.alpha(pixel) < transparent) continue

            // Not white?
            if (Color.red(pixel) < white || Color.green(pixel) < white || Color.blue(pixel) < white) {
                left = x
                if (x > 2) {
                    startY = 2
                }
                break
            }
        }

        // Right Margin
        var right = 0
        for (x in 0 until halfX) {
            val pixel = source.getPixel(width - x, halfY)

            // Transparent?
            if (Color.alpha(pixel) < transparent) continue

            // Not white?
            if (Color.red(pixel) < white || Color.green(pixel) < white || Color.blue(pixel) < white) {
                right = x
                if (x > 2) {
                    startY = 2
                }
                break
            }
        }

        // Top Margin
        var top = 0
        for (y in startY until halfY) {
            val pixel = source.getPixel(halfX, y)

            // Transparent?
            if (Color.alpha(pixel) < transparent) continue

            // Not white?
            if (Color.red(pixel) < white || Color.green(pixel) < white || Color.blue(pixel) < white) {
                top = y
                break
            }
        }

        // Bottom Margin
        var bottom = 0
        for (y in startY until halfY) {
            val pixel = source.getPixel(halfX, height - y)

            // Transparent?
            if (Color.alpha(pixel) < transparent) continue

            // Not white?
            if (Color.red(pixel) < white || Color.green(pixel) < white || Color.blue(pixel) < white) {
                bottom = y
                break
            }
        }

        // Clip, scale and return
        val newWidth = width - (left + right)
        val newHeight = height - (top + bottom)
        val scale = if (abs(newWidth - outWidth) > abs(newHeight - outHeight)) outWidth / newWidth.toFloat() else outHeight / newHeight.toFloat()
        val matrix = Matrix().apply { setScale(scale, scale) }
        return Bitmap.createBitmap(source, left, top, newWidth, newHeight, matrix, false)
    }



    // Caching helpers
    override fun equals(other: Any?): Boolean {
        return other is ClipWhiteTransformation && other.hashCode() == hashCode()
    }
    override fun hashCode(): Int {
        return  ID.hashCode()
    }
    override fun updateDiskCacheKey(messageDigest: MessageDigest) {
        messageDigest.update(ID_BYTES)
    }
}
fun ImageView.setURL(url: String, 
                     @DrawableRes error: Int? = null, 
                     @DrawableRes placeholder: Int? = null, 
                     size: Int? = null, 
                     options: ((RequestBuilder<Drawable>) -> Unit)? = null, 
                     completion: ((resource: Drawable?) -> Unit)? = null) {

    // No URL, use Placeholder if exists, if not, use the error image
    if (url.isEmpty()) {
        placeholder?.also{ setImageResource(it) } ?: run { error?.also{ setImageResource(it) } }
        return
    }

    Glide.with(applicationInstance) // (I'm using an application instance directly here)
        .load(url).apply {
            completion?.also { completion ->
                this.listener(object : RequestListener<Drawable> {
                    override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                        completion(null)
                        return false
                    }
                    override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                        completion(resource)
                        return false
                    }
                })
            }
        }
        .apply { size?.also { this.override(it)} }
        .apply { options?.invoke(this) }
        .placeholder(placeholder ?: 0)
        .error(error ?: 0)
        .transition(DrawableTransitionOptions.withCrossFade(350))
        .into(this)
}
implementation 'com.google.android.material:material:1.3.0-alpha01'
<com.google.android.material.imageview.ShapeableImageView
    android:id="@+id/imgStudent"
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:shapeAppearanceOverlay="@style/circleImageView"
    android:padding="2dp"
    app:strokeColor="@color/white"
    app:strokeWidth="5dp"
    android:scaleType="centerCrop"
    android:adjustViewBounds="true"
    tools:srcCompat="@drawable/ic_kid_placeholder"
    />
<style name="circleImageView" parent="">
        <item name="cornerFamily">rounded</item>
        <item name="cornerSize">50%</item>
        <item name="android:shadowRadius">100</item>
        <item name="android:shadowColor">@color/gray</item>
        <item name="backgroundOverlayColorAlpha">12</item>
</style>