图片加载之Glide使用总结
##概述
作为Glide是谷歌推荐的图片加载库,Glide又着 支持video,Gif,SVG格式,同时有着很好的生命周期管理,支持Volley,OkHttp,更好的内存管理策略等优点。
相关方法
- with():指定了声明周期
- load():加载资源,String/Uri/File/Integer/URL/byte[]/T,或者 loadFromMediaStore(Uri uri)
- placeholder(resourceId/drawable): 设置资源加载过程中的占位Drawable。
- error():load失败时显示的Drawable。
- crossFade()/crossFade(int duration):imageView改变时的动画,version 3.6.1后默认开启300毫秒
- dontAnimate():移除所有的动画。
- override() :调整图片大小
- centerCrop():图片裁剪,ImageView 可能会完全填充,但图像可能不会完整显示。
- fitCenter(): 图像裁剪,图像将会完全显示,但可能不会填满整个 ImageView。
- animate(): 指定加载动画。
- transform():图片转换。
- bitmapTransform(): bitmap转换,不可以和(centerCrop() 或 fitCenter())共用。
- priority(Priority priority):当前线程的优先级,Priority.IMMEDIATE,Priority.HIGH,Priority.NORMAL(default),Priority.LOW
- thumbnail(): 缩略图.
- listener():异常监听
- preload(int width, int height): 预加载resource到缓存中(单位为pixel)
- fallback(Drawable drawable):设置model为空时显示的Drawable。
- using() :为单个的请求指定一个 model
- asGif():Gif 检查,如果是图片且加了判断,则会显示error占位图,否则会显示图片
- asBitmap():bitmap转化,如果是gif,则会显示第一帧
Glide 可以以load(File)的形式播放本地视频,但是如果需要播放网络视屏,则要用VideoView
缓存策略
一张图片变化很快,需要禁止内存缓存
.skipMemoryCache(true)
即使关闭内存缓存,请求图片将会仍然被存储在设备的磁盘缓存中,如果一张图片变化很快,仍需要禁止磁盘缓存
.diskCacheStrategy(DiskCacheStrategy.NONE)
Glide 缓存了原始图像,全分辨率图像和另外小版本的图像,因此禁用磁盘缓存是用枚举来控制的
DiskCacheStrategy.NONE //什么都不缓存,就像刚讨论的那样
DiskCacheStrategy.SOURCE //仅仅只缓存原来的全分辨率的图像。在我们上面的例子中,将会只有一个 1000x1000 像素的图片
DiskCacheStrategy.RESULT //仅仅缓存最终的图像,即,降低分辨率后的(或者是转换后的)
DiskCacheStrategy.ALL //缓存所有版本的图像(默认行为)
Glide使用InternalCacheDiskCacheFactory类建立磁盘缓存。目录在
/data/data/<package-name>/cache
,其他应用程序无法访问。
自定义缓存策略:
磁盘缓存,用类DiskLruCacheWrapper来设置目录
builder.setDiskCache(new DiskCache.Factory() {@Overridepublic DiskCache build() {// 自己的缓存目录File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/package-name");return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);}});
内存缓存,用类Memory Cache 来设置大小
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
Bitmap Pool
重复使用及销毁策略。设置方法:GlideBuilder.setBitmapPool()
默认采用的是LruBitmapPool,使用了LRU算法。
MemorySizeCalculator calculator = new MemorySizeCalculator(context);
int defaultBitmapPoolSize = calculator.getBitmapPoolSize();
int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);
builder.setBitmapPool( new LruBitmapPool( customBitmapPoolSize );
Bitmap Format
Bitmap Format用于设置全局缺省首选Bitmap规格,设置方法:GlideBuilder.setDecodeFormat()
默认采用RGB_565(比ARGB_8888节省一半的内存),但不支持透明度。
优先级
会发现优先级高的先 显示出来,即是图片比较大。
//优先加载Glide.with(context).load(heroImageUrl).priority(Priority.HIGH).into(imageViewHero);//后加载Glide.with(context).load(itemImageUrl).priority(Priority.LOW).into(imageViewItem);
先显示缩略图,后显示原图
//用原图的1/10作为缩略图Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").thumbnail(0.1f).into(iv_0);//用其它图片作为缩略图DrawableRequestBuilder<Integer> thumbnailRequest = Glide.with(this).load(R.drawable.news);Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").thumbnail(thumbnailRequest).into(iv_0);
图片处理
裁剪、模糊、滤镜等。可以s使用 wasabeef/glide-transformations ,
实现Transformation 接口,或者使用抽象类BitmapTransformation,
通过transform()或bitmapTransform()来处理图片
//圆形裁剪Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").bitmapTransform(new CropCircleTransformation(this)).into(iv_0);//圆角处理Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").bitmapTransform(new RoundedCornersTransformation(this,30,0, RoundedCornersTransformation.CornerType.ALL)).into(iv_0);//灰度处理Glide.with(this).load("http://inthecheesefactory.com/uploads/source/nestedfragment/fragments.png").bitmapTransform(new GrayscaleTransformation(this)).into(iv_0);//模糊处理Glide.with(this).load(R.drawable.demo).bitmapTransform(new BlurTransformation(context)).into((ImageView) findViewById(R.id.image));//其它变换...
自定义转换
public class BlurTransformation extends BitmapTransformation {public BlurTransformation(Context context) {super( context );}@Overrideprotected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {return null; // todo}@Overridepublic String getId() {return null; // todo}
}
其中getId() :描述了这个转换的唯一标识符,将作为缓存系统的一部分
可以使用单种转换和多种转换,如多种转换:
Glide .with( context ).load( eatFoodyImages[1] ).transform( new GreyscaleTransformation( context ), new BlurTransformation( context ) ).into( imageView2 );
回调 Target
SimpleTarget
target 泛型:Bitmap,GlideDrawable,GifDrawable
其中使用字段声明target’而不是使用匿名内部类的形式,可以避免被垃圾回收机制回收,而回调为空的现象。
private SimpleTarget target = new SimpleTarget<Bitmap>() { @Overridepublic void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {// do something with the bitmap// for demonstration purposes, let's just set it to an ImageViewimageView1.setImageBitmap( bitmap );}
};private void loadImageSimpleTarget() { Glide.with( context ) // could be an issue!.load( eatFoodyImages[0] ).asBitmap().into( target );
}
Target生命周期
with( context ):关系到生命周期。如果请求需要在 activity 生命周期之外去做时,需要使用:
private void loadImageSimpleTargetApplicationContext() { Glide.with( context.getApplicationContext() ) // safer!.load( eatFoodyImages[1] .asBitmap().into( target2 );
}
Target 指定尺寸
使用ImageView 作为参数给 .into()的时候,Glide 会用 ImageView 的大小去限制图像的大小
但是target并没有已知的大小,如果知道图片大小则应指出,减少内存消耗。
private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) { @Overridepublic void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {imageView2.setImageBitmap( bitmap );}
};private void loadImageSimpleTargetApplicationContext() { Glide.with( context.getApplicationContext() ) // safer!.load( eatFoodyImages[1] ).asBitmap().into( target2 );
}
ViewTarget
常用于自定以控件中,比如自定义控件中组合了ImageView控件,如下
public class FutureStudioView extends FrameLayout { ImageView iv;TextView tv;public void initialize(Context context) {inflate( context, R.layout.custom_view_futurestudio, this );iv = (ImageView) findViewById( R.id.custom_view_image );tv = (TextView) findViewById( R.id.custom_view_text );}public FutureStudioView(Context context, AttributeSet attrs) {super( context, attrs );initialize( context );}public FutureStudioView(Context context, AttributeSet attrs, int defStyleAttr) {super( context, attrs, defStyleAttr );initialize( context );}public void setImage(Drawable drawable) {iv = (ImageView) findViewById( R.id.custom_view_image );iv.setImageDrawable( drawable );}
}
使用如下方法给自定义控件中的ImageView设置图片
private void loadImageViewTarget() { FutureStudioView customView = (FutureStudioView) findViewById( R.id.custom_view );//传递了参数 customViewviewTarget = new ViewTarget<FutureStudioView, GlideDrawable>( customView ) {@Overridepublic void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {//调用了FutureStudioView的setImage方法this.view.setImage( resource.getCurrent() );}};Glide.with( context.getApplicationContext() ) // safer!.load( eatFoodyImages[2] ).into( viewTarget );
}
NotificationTarget
用于加载图片到通知栏和应用小部件中的,具体见 http://mrfu.me/
动画
animate() :可以加载资源文件animate.xml文件
或者 属性动画:
- ViewPropertyAnimation
- ViewAnimation
- NoAnimation
- DrawableCrossFadeViewAnimation
ViewPropertyAnimation.Animator animationObject = new ViewPropertyAnimation.Animator() { @Overridepublic void animate(View view) {// if it's a custom view class, cast it here// then find subviews and do the animations// here, we just use the entire view for the fade animationview.setAlpha( 0f );ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );fadeAnim.setDuration( 2500 );fadeAnim.start();}
};Glide .with( context ).load( eatFoodyImages[1] ).animate( animationObject ).into( imageView2 );
Glide module
Glide module 是一个抽象方法,全局改变 Glide 行为的一个方式。
前面单策略的定义中都用到了GlideBuilder类
如果你需要访问 GlideBuilder,你需要去实现一个 GlideModule 接口的公共类
public class FileGlideModule implements GlideModule{@Overridepublic void applyOptions(final Context context, GlideBuilder builder) {//builder 内的所有方法你都可以设置。
// builder.setDiskCache(new InternalCacheDiskCacheFactory(context));builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));/* builder.setDiskCache(new DiskCache.Factory() {@Overridepublic DiskCache build() {File imgFile = new File(Environment.getExternalStorageDirectory()+"/Android/data/com.leying365");return DiskLruCacheWrapper.get(imgFile,DiskCache.Factory.DEFAULT_DISK_CACHE_SIZE);}});*/MemorySizeCalculator calculator = new MemorySizeCalculator(context);builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));builder.setBitmapPool(new LruBitmapPool(calculator.getBitmapPoolSize()));builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);}@Overridepublic void registerComponents(Context context, Glide glide) {}
}
最终通过<meta-data android:name=”com.mypackage.MyGlideModule” tools:node=”GlideModule” />
来生效
常用方法:
- setMemoryCache(MemoryCache memoryCache)
- setBitmapPool(BitmapPool bitmapPool)
- setDiskCache(DiskCache.Factory diskCacheFactory)
- setDiskCacheService(ExecutorService service)
- setResizeService(ExecutorService service)
- setDecodeFormat(DecodeFormat decodeFormat)
网络库
Glide 使用ModeLoader 接口来 集成网络库,Glide提供了两种网络库 的实现,分别为OkHttp 和 Volley。
在build.gradle中添加如下依赖,glide会默认使用OKhttp来做所有的网络连接
dependencies { // your other dependencies// ...// Glidecompile 'com.github.bumptech.glide:glide:3.6.1'// Glide's OkHttp Integration compile 'com.github.bumptech.glide:okhttp-integration:1.3.1@aar'compile 'com.squareup.okhttp:okhttp:2.5.0'
}
上面会将必要的GlideModule 到你的 Android.Manifest中。
缓存与失效机制
Glide 通过 url、viewwidth、viewheight、屏幕的分辨率等以一种散列算法生成一个独有、安全的文件名作为key保存到disk上.因为其是通过一个散列算法来实现的,因此很难定位文件的缓存,幸好Glide提供了signature()方法允许将一个附加的数据加入到缓存key当中,可以用来保证缓存的及时性.
系统默认实现了MediaStoreSignature,StringSignature.
Glide.with(fragment).load(mediaStoreUri).signature(new MediaStoreSignature(mimeType, dateModified, orientation)).into(view);
当然也可以自己来实现Signature
public class MSignature implements Key {@Overridepublic boolean equals(Object o) {//...}@Overridepublic int hashCode() {//...}@Overridepublic void updateDiskCacheKey(MessageDigest messageDigest) {messageDigest.update(ByteBuffer.allocate(Integer.SIZE)
.putInt(signature).array());}
}
极端情况,不缓存可以用diskCacheStrategy(DiskCacheStrategy.NONE.)
来实现
图片下载
Glide除了提供into方法来加载图片外,也提供了downloadOnly方法来实现图片下载.
FutureTarget<File> future = Glide.with(applicationContext).load(yourUrl).downloadOnly(500, 500);
File cacheFile = future.get();
下载之后可以通过如下方式来加载图片
Glide.with(yourFragment).load(yourUrl)//DiskCacheStrategy.ALL或者DiskCacheStrategy.SOURCE可以保证程序会先去读缓存文件.diskCacheStrategy(DiskCacheStrategy.ALL).into(yourView);
如果想获取一张图片的Bitmap,可以使用如下方式
//此方法需要try/catch处理,并且最好在子线程中,否则会阻塞主线程
Bitmap myBitmap = Glide.with(applicationContext).load(yourUrl).asBitmap().centerCrop()//设置大小.into(500, 500).get()
参考:http://mrfu.me/
使用demo:GlidePlayActivity.java
图片加载之Glide使用总结相关推荐
- 图片加载框架Glide的简单使用
图片加载框架Glide的相关使用 一.搭建环境 1.引入依赖,设置网络权限 implementation 'com.github.bumptech.glide:glide:3.7.0' 代码实现 1. ...
- Google图片加载库Glide的简单封装GlideUtils
Google图片加载库Glide的简单封装GlideUtils
- Android之Google推荐的图片加载库Glide介绍
原文链接:Google推荐的图片加载库Glide介绍 作者 : nuuneoi 译者 : jianghejie 校对者 :
- Google推荐的图片加载库Glide于Picasso比较
在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官 ...
- Android图片加载框架——Glide(Glide v4)
原文地址 Android图片加载框架--Glide(Glide v4) 前言 android中图片加载框架有很多,所有框架最终达到的目都是在Android平台上以极度简单的方式加载和展示图片,如果我们 ...
- 详谈高大上的图片加载框架Glide -应用篇
在Android设备上,加载网络图片一直是一个头疼的问题,因为Android设备种类繁多(当然最主要的是配置),处理的稍不周到轻则应用卡顿,严重者就会出现OOM的,导致程序挂掉.现如今网络上有很多图片 ...
- 详谈高大上的图片加载框架Glide -源码篇
在上篇文章中,我们介绍了Glide图片加载框架的使用,通过之前的学习,我们可能已经能熟练的将Glide图片加载框架运用到我们的项目中,但是如果有人问你它是如何加载,工作原理是怎样的?为什么自定义Gli ...
- Android开源框架——图片加载库Glide
Glide是有google开发的图片加载库,支持图片加载与处理,包括动态图片的加载,以及视频的解码. 开源地址:https://github.com/bumptech/glide build.grad ...
- android 图片加载库 Glide 的使用介绍
一:简介 在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech.这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会 ...
- android图片加载库Glide
什么是Glide? Glide是一个加载图片的库,作者是bumptech,它是在泰国举行的google 开发者论坛上google为我们介绍的,这个库被广泛的运用在google的开源项目中. Glide ...
最新文章
- tensorflow-gpu
- 三天打入CV大赛决赛圈!我是如何做到的?
- Android逆向之路---脱壳360加固
- MySQL limit 优化,百万至千万级快速分页:复合索引
- 【竞赛题解】Codeforces Round #715 (Div. 2) C
- PHP的html实现xpath解析,php用xpath解析html的代码实例讲解
- Js实现动态插入删除文本框
- java回合制武侠手游_App Store 上的“群侠传-怀旧开放武侠RPG回合制手游”
- Android实例-手机安全卫士(三十五)-来电号码显示归属地
- Windows的拖放操作使用方法
- 利用python进行数据分析—8.数据清洗与准备
- 捡到iphone6怎么解锁_赛博朋克2077前期手枪用哪个好?2077节制结局及银杯节制解锁条件...
- JuniperSSG140使用PBR实现双线路接入
- 80后 程序猿 单恋10年,是一种怎样的体验?
- uniapp获取用户数据昵称为“微信用户”(小程序)@杨章隐
- Qgis教程6:创建矢量数据
- kafka(一):kafka架构
- JavaScript 01 JavaScript 是什么
- EMP平台简介(转载)
- (翻译)峰终定律(Peak-end rule)
热门文章
- c# messageboxbutons.ok,MessageBoxIcon.Information 是什么意思
- [收藏]大话西游的三个人生片段
- 硕士码农的offer档次排行(个人版)
- 网站的SEO外链你需要怎么发
- Pytorch使用GPU训练模型加速
- RFC 请求评议 潇湘博客
- 巧克力慕斯的制作方法
- 超高颜值难以抵挡 乐泡淳移动电源体验
- 迷你世界电路计算机的过程,迷你世界循环电路怎么做 迷你世界循环电路制作攻略...
- 俄罗斯最先进的计算机系统,世界上最先进的防空导弹系统:俄S-400实力强大,堪称空天防御的集大成者...