上一篇中利用RecyclerView已经实现了将控件复用以达到减少性能和内存消耗的目的,这一篇中将进一步优化界面的显示。
我项目中采用的图片加载框架是Glide,优点什么的网上很多人都在讨论,这里说一下我为什么选用Glide而不是Picasso、Fresco等。
1、图片的加载请求和与之相关Context的生命周期是相关联的,
这一点对于此项目是有很大优势的,可以减少不必要的性能消耗。由于项目的界面主结构是由fragment组成的,且各fragment都要加载大量的图片,当fragment切换时生命周期变化会触发Glide自动的将请求进行暂停和恢复操作,从而节约流量和内存,并且防止内存泄露。
2、图片加载后的展示效果,相信很多知道Glide的人都有见过Glide加载图片时渐显的酷炫动画效果,这一点主要体现在用户的感官上。
主要原因是以上两点,由于Glide默认设置已经有了内存缓存和磁盘缓存策略,如果不是硬性需要可使用默认。
说了这么多本文主要讲的要来了“图片处理”,如何自定义BitmapTransformation
先看看对比图
是不是给人一种生硬的感觉,图片都是有棱有角的不是很顺滑,还好官方给出了处理办法BitmapTransformation
BitmapTransformation是一个抽象类,需要实现的方法如下
//toTransform为源
protected abstract Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight);
/**
* Created by mr.lin on 2018/1/14.
* 圆角图片转换
*/
class GlideRoundTransform(context: Context, private var radius: Int) : BitmapTransformation(context) {
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap? {
return roundCrop(pool, toTransform)
}
private fun roundCrop(pool: BitmapPool, source: Bitmap): Bitmap {
var result = pool.get(source.width, source.height, Bitmap.Config.ARGB_8888)
if (result == null) {
result = Bitmap.createBitmap(source.width, source.height, Bitmap.Config.ARGB_8888)
}
//这时result只是一张指定了大小的空图,如果要求不高的话可以更改ARGB_8888以减少内存消耗
val canvas = Canvas(result)
val paint = Paint()
paint.shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paint.isAntiAlias = true
val rectF = RectF(0f, 0f, source.width.toFloat(), source.height.toFloat())
canvas.drawRoundRect(rectF, radius.toFloat(), radius.toFloat(), paint)
//操作其实很简单就是画了一个圆角矩形
return result
}
//用于标示BitmapTransformation,接口Transformation<T> 有解释用以标示唯一对象的key
override fun getId(): String {
return this.javaClass.name
}
}
过程并不是一帆风顺的
同一张图片发现问题了吗?过程图中的图片被裁剪了。。。。。
由于我在布局的时候对ImageView的宽高进行了指明,导致加载大图的时候会以左上角坐标进行裁剪,当改变ImageView宽高为wrap_content时才显示正常。
/**
* Created by mr.lin on 2018/1/15.
* 圆形图片转换
*/
class GlideCircleTransform(context: Context?) : BitmapTransformation(context) {
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
return circleCrop(pool, toTransform)
}
private fun circleCrop(pool: BitmapPool, source: Bitmap): Bitmap {
val size = Math.min(source.width, source.height)
val x = (source.width - size) / 2
val y = (source.height - size) / 2
val squared = Bitmap.createBitmap(source, x, y, size, size)
var result = pool.get(size, size, Bitmap.Config.ARGB_8888)
if (result == null) {
result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
}
val canvas = Canvas(result)
val paint = Paint()
paint.shader = BitmapShader(squared, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
paint.isAntiAlias = true
val r = size / 2f
canvas.drawCircle(r, r, r, paint)
return result
}
override fun getId(): String {
return this.javaClass.name
}
}
当然所有的图片加载都要封装到一起,以免以后更换图片加载框架
/**
* Created by mr.lin on 2018/1/14.
* glide工具
*/
class GlideUtils {
companion object {
fun loadImage(context: Context, url: String, iv: ImageView) {
Glide.with(context)
.load(url)
.into(iv)
}
fun loadRoundImage(context: Context, url: String, iv: ImageView, radius: Int) {
Glide.with(context)
.load(url)
.transform(GlideRoundTransform(context, CommonUtils.dpTopx(radius.toFloat())))
.into(iv)
}
fun loadCircleImage(context: Context, url: String, iv: ImageView) {
Glide.with(context)
.load(url)
.transform(GlideCircleTransform(context))
.into(iv)
}
}
}