问题
I have the following custom transformation (kotlin):
private class IconTransformation : BitmapTransformation() {
companion object {
private const val ID = "com.example.widget.IconView\$IconTransformation"
private val ID_BYTES = ID.toByteArray()
private const val PAINT_FLAGS = Paint.DITHER_FLAG or Paint.FILTER_BITMAP_FLAG
private const val CIRCLE_CROP_PAINT_FLAGS = PAINT_FLAGS or Paint.ANTI_ALIAS_FLAG
private val CIRCLE_CROP_SHAPE_PAINT = Paint(CIRCLE_CROP_PAINT_FLAGS)
private val CIRCLE_CROP_BITMAP_PAINT = Paint(CIRCLE_CROP_PAINT_FLAGS).apply {
xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
}
private val CLEAR_PAINT = Paint().apply {
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
}
}
override fun updateDiskCacheKey(messageDigest: MessageDigest) {
messageDigest.update(ID_BYTES)
}
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int,
outHeight: Int): Bitmap {
val img = TransformationUtils.fitCenter(pool, toTransform, outWidth, outHeight)
val result = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888)
val left = (result.width - img.width) / 2f
val top = (result.height - img.height) / 2f
result.setHasAlpha(true)
Canvas(result).apply {
drawColor(Color.TRANSPARENT)
drawCircle(outWidth / 2f, outHeight / 2f,
Math.min(outWidth, outHeight) / 2f, CIRCLE_CROP_SHAPE_PAINT)
drawBitmap(img, left, top, CIRCLE_CROP_BITMAP_PAINT)
if (left > 0f) {
drawRect(0f, 0f, left, outHeight.toFloat(), CLEAR_PAINT)
drawRect(left + img.width - 1, 0f,
outWidth.toFloat(), outHeight.toFloat(), CLEAR_PAINT)
}
if (top > 0f) {
drawRect(0f, 0f, outWidth.toFloat(), top, CLEAR_PAINT)
drawRect(0f, top + img.height - 1,
outWidth.toFloat(), outHeight.toFloat(), CLEAR_PAINT)
}
}
pool.put(img)
return result
}
override fun hashCode(): Int = ID.hashCode()
override fun equals(other: Any?): Boolean = other is IconTransformation
}
When I use it like below inside a recycler view, the images flicker and bounce around. From everything I read it has to do with improperly implementing updateDiskCacheKey
, hashCode
, and equals
. From AFAIK I followed the instructions in BitmapTransformation
exactly.
Glide.with(icon)
.load(url)
.apply(RequestOptions()
.transform(IconTransformation())
.error(errorDrawableRes))
.into(icon)
回答1:
My comment here might help.
I use placeholder to solve the flickering problem. dontTransform does not work in my app. After search around the source code of Glide, I find the problem might come from ImageViewTarget:
/** * Sets the given {@link android.graphics.drawable.Drawable} on the view using {@link * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}. * * @param placeholder {@inheritDoc} */ @Override public void onLoadStarted(@Nullable Drawable placeholder) { super.onLoadStarted(placeholder); setResourceInternal(null); setDrawable(placeholder); }
Thus if placeholder is null, ImageView will turn blank right after every loading. So I cache the last image in the ImageView and set it as placeholder for next loading. Here is the code
// init mGlideOpt = new RequestOptions().dontAnimate().skipMemoryCache(false); mGlideRB = Glide.with(imageView).asBitmap(); // loading Drawable drawable = mImageView.getDrawable(); if (drawable != null) { mGlideOpt = mGlideOpt.placeholder(drawable); } mGlideRB.apply(mGlideOpt).load(mCacheFile).into(mImageView);
Just a work around. Hope it helps.
回答2:
The issue was in the line pool.put(img)
turning into the following fixed the issue:
if (img != toTransform) {
pool.put(img)
}
来源:https://stackoverflow.com/questions/48996119/glide-4-6-1-image-flicker-on-custom-transformation