前言
接着上面的几篇文章,这篇来说说图片加载问题,在Android
应用中图片加载这个问题是少不了的,从曾经的ImageLoader
到现在的Glide
,Picasso
,Freseo
。如果从Github
的Star
来说,Glide
相对来说用的更多些。
简单比较
其实这三个图片加载框架的比较,Google
上已经有很多说法了,这里简单的总结说下:
Freseo
-
SimpleDraweeView
代替Android
的ImageView
- 三级缓存,
Bitmap
缓存,内存缓存,磁盘缓存 - 缓存原始图像
- 5.0以下系统,会将图片放在特殊的区域
Ashmem
区,减下OOM
的出现 - 加载图片质量相对
Glide
更高 - 支持圆形图片和带边框的圆形图片
- 获取
Bitmap
不方便
picasso
- 不支持
gif
- 加载速度,内存消耗,相对来说没有优势
Glide
- 内存消耗小
- 使用
RGB_565
加载 - 根据图片大小缓存图片
-
API
使用简单 - 需要自己通过定义
BitmapTransformation
实现圆角和圆形图片 - 在没有缓存的情况下,加载速度略低于
Freseo
结论:
Freseo
适合社交类的应用,对图片质量相对较高的APP
,三级缓存,性能相对来说略高,但是包大小相对来说更大,得使用SimpleDraweeView
,Glide
性能也不会低太多,使用简单,集成方便,耦合性低,Google
自己的产品。
Glide
这里结合Github
的glide-transformations
处理圆形图片,毛玻璃效果的图片更加方便。
下面对Glide
进行简单的封装
object GlideUtils{
fun loadNormalImageView(imageView: ImageView,url:String,loadingResId:Int ? = R.color.defE2,
errorResId:Int? =R.color.defE2,listener:RequestListener<String,GlideDrawable>? = null){
baseGlide()
.load(url)
.listener(listener)
.placeholder(loadingResId!!.toInt())
.error(errorResId!!.toInt())
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.dontAnimate()
.into(imageView)
}
fun loadCircleImageView(imageView: ImageView,url:String,loadingResId:Int ? = R.color.defE2,errorResId:Int? =R.color.defE2){
baseGlide()
.load(url)
.placeholder(loadingResId!!.toInt())
.error(errorResId!!.toInt())
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.bitmapTransform(CropCircleTransformation(AppBridge.AppContext()))
.dontAnimate()
.priority(Priority.HIGH)
.into(imageView)
}
fun loadBorderCircleImageView(imageView: ImageView,url:String,loadingResId:Int ? = R.color.defE2,errorResId:Int? =R.color.defE2){
baseGlide()
.load(url)
.placeholder(loadingResId!!.toInt())
.error(errorResId!!.toInt())
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.bitmapTransform(BorderCircleTransformation(AppBridge.AppContext(), 2, Color.WHITE))
.dontAnimate()
.priority(Priority.HIGH)
.into(imageView)
}
fun loadNormalFileImageView(imageView:ImageView,localFile: File){
baseGlide()
.load(localFile.absolutePath)
.crossFade()
.priority(Priority.HIGH)
.into(imageView)
}
fun loadBlur(context: Context, imageView: ImageView, url: String) {
baseGlide().load(url)
.bitmapTransform(BlurTransformation(context, 20)).into(imageView)
}
fun loadBlur(context: Context, imageView: ImageView, file: File) {
baseGlide().load(file)
.bitmapTransform(BlurTransformation(context, 20)).into(imageView)
}
fun loadBlur(context: Context, imageView: ImageView, res: Int) {
baseGlide().load(res).bitmapTransform(BlurTransformation(context, 20)).into(imageView)
}
fun loadBlur(context: Context, imageView: ImageView, drawable: Drawable) {
baseGlide().load(drawable).bitmapTransform(BlurTransformation(context, 20)).into(imageView)
}
fun loadBlur(context: Context, imageView: ImageView, bitmap: Bitmap) {
val baos = ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos)
baseGlide().load(baos.toByteArray()).bitmapTransform(BlurTransformation(context, 20)).into(imageView)
}
fun loadBitmap(url: String, simpleTarget: SimpleTarget<Bitmap>) {
Glide.with(AppBridge.AppContext())
.load(url)
.asBitmap()
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.SOURCE)
.dontAnimate()
.into(simpleTarget)
}
fun baseGlide():RequestManager{
return Glide.with(AppBridge.AppContext())
}
}
然后通过Transformation<Bitmap>
实现带边框的图片
public class BorderCircleTransformation implements Transformation<Bitmap> {
private BitmapPool mBitmapPool;
private Paint mBorderPaint;
private float mBorderWidth;
public BorderCircleTransformation(Context context){
this(Glide.get(context).getBitmapPool());
}
public BorderCircleTransformation(BitmapPool pool){
this.mBitmapPool = pool;
}
public BorderCircleTransformation(Context context, int borderWidth, int borderColor){
this(context);
mBorderWidth = Resources.getSystem().getDisplayMetrics().density * borderWidth;
mBorderPaint = new Paint();
mBorderPaint.setDither(true);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(ContextCompat.getColor(context,borderColor));
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setStrokeWidth(mBorderWidth);
}
@Override
public Resource<Bitmap> transform(Resource<Bitmap> resource, int outWidth, int outHeight) {
Bitmap source = resource.get();
int size = Math.min(source.getWidth(), source.getHeight());
int width = (source.getWidth() - size) / 2;
int height = (source.getHeight() - size) / 2;
Bitmap bitmap = mBitmapPool.get(size, size, Bitmap.Config.ARGB_8888);
if (bitmap == null) {
bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
}
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader =
new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
if (width != 0 || height != 0) {
// source isn't square, move viewport to center
Matrix matrix = new Matrix();
matrix.setTranslate(-width, -height);
shader.setLocalMatrix(matrix);
}
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
float borderRadius = r - mBorderWidth / 2;
canvas.drawCircle(borderRadius, borderRadius, borderRadius, paint);
if (mBorderPaint != null) {
canvas.drawCircle(r, r, borderRadius, mBorderPaint);
}
return BitmapResource.obtain(bitmap, mBitmapPool);
}
@Override
public String getId() {
return "BorderCircleTransformation()";
}
}