Android——Glide的使用详解

来源:互联网 发布:u盘数据丢失恢复 编辑:程序博客网 时间:2024/05/16 08:50

Glide是谷歌为我们推荐的一个图片加载库。为什么要选择使用Glide呢?

  • 1、代码有人维护,不至于出现问题,项目组都搞不定的时候问题无法解决。(ImageLoader已没人维护了)
  • 2、代码简洁,可读性很好。(Fresco是一个非常优秀的库,但是配置稍显麻烦,同时代码风格读起来有些生疏)
  • 3、功能强大(400多k的包,包含很多功能,例如:像加载Gif图片就是Picasso做不到的)

下面我们就来介绍下Glide的用法:

Glide的基本使用

导入库

repositories {  mavenCentral() // jcenter() works as well because it pulls from Maven Central}dependencies {  compile 'com.github.bumptech.glide:glide:3.7.0'  compile 'com.android.support:support-v4:19.1.0'}

添加代码混淆

-keep public class * implements com.bumptech.glide.module.GlideModule-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {  **[] $VALUES;  public *;}# for DexGuard only-keepresourcexmlelements manifest/application/meta-data@value=GlideModule

简单使用例子

// For a simple view:@Override public void onCreate(Bundle savedInstanceState) {  ...  ImageView imageView = (ImageView) findViewById(R.id.my_image_view);  Glide.with(this).load("http://goo.gl/gEgYUd").into(imageView);}// For a simple image list:@Override public View getView(int position, View recycled, ViewGroup container) {  final ImageView myImageView;  if (recycled == null) {    myImageView = (ImageView) inflater.inflate(R.layout.my_image_view, container, false);  } else {    myImageView = (ImageView) recycled;  }  String url = myUrls.get(position);  Glide    .with(myFragment)    .load(url)    .centerCrop()    .placeholder(R.drawable.loading_spinner)    .crossFade()    .into(myImageView);  return myImageView;}

Glide使用详解

加载网络图片

Glide.with(context).load(internetUrl).into(targetImageView);

从文件加载图片

File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"Test.jpg");Glide.with(context).load(file).into(imageViewFile);

从资源id加载图片

int resourceId = R.mipmap.ic_launcher;Glide.with(context).load(resourceId).into(imageViewResource);

从uri加载图片

Glide.with(context).load(uri).into(imageViewUri);

播放本地mp4,只能是本地

String filePath = "/storage/emulated/0/Pictures/example_video.mp4";Glide.with( context ).load( Uri.fromFile( **new **File( filePath ) ) ).into( imageViewGifAsBitmap );

加载Gif图片

String gifUrl = "xxxxx";Glide.with( context ).load( gifUrl ).into( imageViewGif );

用bitMap播放Gif.asBitmap()

Glide.with( context ).load( gifUrl ).asBitmap().into( imageViewGifAsBitmap );

强制转化为Gif.asGif()

Glide.with( context ).load( gifUrl ).asGif().error( R.drawable.full_cake ).into( imageViewGif );

设置默认占位图.placeholder()

设置加载失败的图片.error()

Glide.with( context ).load( gifUrl ).placeholder( R.drawable.cupcake ).error( R.drawable.full_cake ).into( imageViewGif );

.fallback()

除了上面两种‘异常情况’,还有一种情形就是打开手机的通讯录的时候,可以看到你给有些喜欢的人设置了照片,然而有些可怜的人并没给有,总不能在那里留下一片空白吧,这个时候相当于传递了Null,传递null时,这个callback方法就会被调用。

Glide.with(context)     .load( null)//加载空指针的时候     .fallback( R.drawable.wuyanzu)     .into( imageViewNoFade );

设置加载动画

其实这个是默认的,但是你还是可以写出来,渐显动画
1、.crossFade() :Glide提供淡如淡出

Glide.with(context).load().placeholder(R.mipmap.ic_launcher) .error(R.mipmap.future_studio_launcher).crossFade().into(imageViewFade);

这里还有一个.fadeFade(int duration),设置动画时间。如果你不想要动画可以加上.dontAnimate()
2、.animate(android.R.anim.slide_in_left):Android系统提供,从左到右滑出加载动画

调整图片大小.resize(int ,int )

单位是像素,裁剪你的图片大小。其实Glide已经会自动根据你ImageView裁剪照片来放在缓存中了。但是不想适应ImageView大小的时候,可以调用这个方法.override()为ImageView指定大小。

Glide.with(context).load(image).override(600, 200) .into(imageViewResize);

裁剪图片.fitCenter().CenterCrop()

Glide清楚在合适的ImageView中加载合适的Image.当需要裁剪大小时,有个.centerCrop方法,这个方法的裁剪会让你的ImageView周围不会留白,还有一个.fitCenter()方法,表示让你的Image完全显示,尺寸不对时,周围会留白。

设置缩略图.thumbnail()

.thumbnail()方法的目的就是让用户先看到一个低解析度的图,点开后,再加载一个高解析度的图。

//表示为原图的十分之一Glide.with( context ).load(image).thumbnail( 0.1f ).into( imageView2 );

一种更高级的缩略图加载方式:

当缩略图也需要通过网络加载全部解析度的时候。

private void loadImageThumbnailRequest() {    DrawableRequestBuilder<String> thumbnailRequest = Glide.with( context ).load( eatFoodyImages[2] );    Glide.with( context ).load( UsageExampleGifAndVideos.gifUrl ).thumbnail( thumbnailRequest ).into( imageView3 );}

设置图片显示效果(圆角、圆形、高斯模糊、蒙板、裁剪等等).bitmapTransform()

参考文章:
Glide、Fresco、Picasso 的背后竟然还有如此强大的图片处理库

Glide.with(this).load(R.mipmap.ic_image_sample)     //模糊     .bitmapTransform(new BlurTransformation(this))     //圆角     .bitmapTransform(new RoundedCornersTransformation(this, 24, 0, RoundedCornersTransformation.CornerType.ALL))     //遮盖     .bitmapTransform(new MaskTransformation(this, R.mipmap.ic_launcher))     //灰度     .bitmapTransform(new GrayscaleTransformation(this))     //圆形     .bitmapTransform(new CropCircleTransformation(this))     .into(mResultIv);

除此之外还有实现诸如马赛克、明暗度等更多滤镜处理:

  • ToonFilterTransformation
  • SepiaFilterTransformation
  • ContrastFilterTransformation
  • InvertFilterTransformation
  • PixelationFilterTransformation
  • SketchFilterTransformation
  • SwirlFilterTransformation
  • BrightnessFilterTransformation
  • KuwaharaFilterTransformation
  • VignetteFilterTransformation

Glide的缓存

用过手机的都知道,当划上划下一个ListView的时候,第二次都比第一次快,就是因为为GlideView对资源进行了缓存,而且封装的很好,甚至不需要自己去设定缓存大小,Glide会智能地自己给我们根据设备设置缓存大小。

缓存是为了减少或者杜绝多的网络请求。为了避免缓存,Glide用了内存缓存和‘外存缓存机制’,并且 提供了相应的方法,完全封装,不需要处理细节。Glide会自动缓存到内存,除非调用.skipMemoryCache( true )。尽管调用了这个,Glide还是会缓存到外存,还有一种情形,就是有一张图片,但是这张图变化非常快,这个时候可能并不想缓存到外存中,就使用.diskCacheStrategy( DiskCacheStrategy.NONE )。如果你两种都不需要,可以两个方法组合着一起使用。

自定义外存缓存机制

Glide默认会缓存Image的很多个版本,比如原图,如果你的imageView大小的缓存。.diskCacheStrategy()有以下几种缓存策略:

  • DiskCacheStrategy.NONE 什么都不缓存
  • DiskCacheStrategy.SOURCE 只缓存最高解析图的image
  • DiskCacheStrategy.RESULT 缓存最后一次那个image,比如有可能你对image做了转化
  • DiskCacheStrategy.ALL image的所有版本都会缓存
Glide.with( context ).load( image ).diskCacheStrategy( DiskCacheStrategy.SOURCE ).into( imageViewFile );

修改缓存大小、位置、加载图片质量

和指定HttpClent为OkHttp一样,只不过我们需要配置一些信息在applyOptions()函数里面

public class GlideConfigModule implements GlideModule {    @Override    public void applyOptions(Context context, GlideBuilder builder) {        // 指定位置在packageName/cache/glide_cache,大小为MAX_CACHE_DISK_SIZE的磁盘缓存        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));        //指定内存缓存大小        builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));        //全部的内存缓存用来作为图片缓存        builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));        builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);//和Picasso配置一样    }    @Override    public void registerComponents(Context context, Glide glide) {    }}
 <meta-data            android:name="com.example.imageloadpk.adapter.config.GlideConfigModule"            android:value="GlideModule"/>

一般的图片加载框架设置了磁盘缓存和内存缓存就行了,但是Glide还设置了一个图片缓存。
图片缓存 <= 内存缓存

builder.setDiskCache(new InternalCacheDiskCacheFactory(context, "glide_cache", ConfigConstants.MAX_CACHE_DISK_SIZE));        //指定内存缓存大小        builder.setMemoryCache(new LruResourceCache(ConfigConstants.MAX_CACHE_MEMORY_SIZE));        //全部的内存缓存用来作为图片缓存        builder.setBitmapPool(new LruBitmapPool(ConfigConstants.MAX_CACHE_MEMORY_SIZE));

这里Glide不仅可以缓存图片,还可以缓存其他文件譬如视频之类,也就是说可以把他作为我们的缓存工具来使用,当然缓存方式还是使用LRU。这样我们就不必再去重新集成LruCache和DiskLruCache,再去申请空间,配置。直接可以复用Glide的。

使用缓存也加载动画

但是,动画默认是在图片没有缓存的情况下才加载,想想也是合理的,如果图片已近下载到本地加载速度将会非常快,这个时候使用动画过渡反而碍事。要让从缓存中图片呈现也加载动画不能通过这种方式实现,可以用监听器来做。

   private RequestListener<String, GlideBitmapDrawable> mAnimationRequestListener = new RequestListener<String, GlideBitmapDrawable>() {        @Override        public boolean onException(Exception e, String model, Target<GlideBitmapDrawable> target, boolean isFirstResource) {            return false;        }        @Override        public boolean onResourceReady(GlideBitmapDrawable resource, String model, Target<GlideBitmapDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {            dissProgress();            if (isFromMemoryCache) {            //如果是从缓存加载,设置动画效果                mIvShow.setAnimation(AnimationUtils.loadAnimation(mContext, R.anim.scale));            }            //返回true表示拦截不再传递,false表示事件会传递下去            return false;        }    };

请求优先级.priority()

加载图片肯定也是有先后顺序,Glide提供了.priority()这个方法,它接收以下几个参数:

  • Priority.LOW
  • Priority.NORMAL
  • Priority.HIGH
  • Priority.IMMEDIATE

但是Glide并不一定会按照你的顺序来,只是尽量按照你的顺序来。(比如给一张很大的图片最高的优先权,但是它并不一定比低优先级的图先加载出来,这个时候只有使用缩略图了)

Glide.with(mContext).load(Url.IMAGE_URL_TROCHILIDAE)     .priority(Priority.HIGH).into(mIvTonyRight);

利用callback在非标准情况下加载图片

上面所有的情况都是加载图片到ImageView中,但是并不是所有的情况都是这样。譬如加载的控件类型不是ImageView,是个自定义的布局。或者加载为Background的形式。
可以使用SimpleTarget类型,这里指定他的大小为500*100,加载为背景图片。

.into(new SimpleTarget<Drawable>(500, 100) {    @Override    public void onResourceReady(Drawable resource, GlideAnimation<? super Drawable> glideAnimation) {        mBtnClear.setBackground(resource);    }

同理下载图片原理是一样

.into(new SimpleTarget<Bitmap>() {    @Override    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {        //toSave        Log.d(TAG, "onResourceReady: save successful");    }});

Glide中的回调:Targets

从上面的介绍,已经可以看出Glide内部封装了所有的细节,什么网络请求,什么缓存机制,当所有都就绪过后,自动切换回UI线程,更新ImageView。Targets就是Glide中的回调,当异步线程中所有的工作做完过后返回结果。说白了就是,当请求图片完成后,需要回调的方法。

SimpleTarget

private SimpleTarget target = new SimpleTarget<Bitmap>() {    @Override    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {        // do something with the bitmap        // for demonstration purposes, let's just set it to an ImageView        imageView1.setImageBitmap( bitmap );    }};private void loadImageSimpleTarget() {    Glide.with( context ) *// could be an issue!*         .load( eatFoodyImages[0] )         .asBitmap()//强制Glide返回一个Bitmap         .into( target );}

注意事项:

1、上面这段代码不要写成匿名内部类的机制,原因就是java的自动垃圾回收机制可能在图片还没有加载好的时候就已经把你的Target回收了。

2、注意.with()里面的参数,Glide的请求是和传进去的Context共存亡的,如果传一个Activity进去,当Activity GC过后,你的请求也就GC了,但是如果这样传:.with(context.getApplicationContext() ).当你的Activity GC过后,请求还是会继续,回调还是会继续。
有size的Target

如果传给into().的是一个ImageView,但是图片的size比ImageView的Size打,Glide为了节省时间,会加载小的那个size的Image。但是这对Target并不适用,以为这里并不知道SIze。但是如果知道image应该多大,可以传递给Target.就像下面这样:

private SimpleTarget target2 = new SimpleTarget<Bitmap>( 250, 250 ) {    @Override    public void onResourceReady(Bitmap bitmap, GlideAnimation glideAnimation) {        imageView2.setImageBitmap( bitmap );    }};private void loadImageSimpleTargetApplicationContext() {    Glide.with(context.getApplicationContext()); *// safer!*         .load( eatFoodyImages[1] )         .asBitmap()         .into( target2 );}

ViewTarget

适用于想Glide加载到自定义View中去,

public class FutureStudioView extends FrameLayout {    ImageView iv;    TextView tv;    public void nitialize(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 );    }}

还有notificationTarget 和AppWidget作为扩展自行研究喽。

监听器配置.listener()

Glide.with(getContext()).load(url)     .listener(mRequestListener)//配置监听器     .placeholder(Drawables.sPlaceholderDrawable)     .error(Drawables.sErrorDrawable)     .into(mImageView);private RequestListener<String, GlideDrawable> mRequestListener = new RequestListener<String, GlideDrawable>() {        @Override        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {            //显示错误信息            Log.w(TAG, "onException: ", e);            //打印请求URL            Log.d(TAG, "onException: " + model);            //打印请求是否还在进行            Log.d(TAG, "onException: " + target.getRequest().isRunning());            return false;        }        @Override        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {            return false;        }    };

这里的onException捕获异常,如果返回true表示我们自己处理掉了异常,false表示交给Glide去处理,因为我们定义了.error()那么就显示error里面的内容。

这里onResourceReady表示是否准备资源显示,返回true表示用户自己已经设置好资源,包括截取操作,动画操作之类的,准备好显示。false表示交给Glide

如此修改后,就能够看到图片加载日志了,方便我们调试。

替换掉自带的HttpClient

只需两步
Step1:
导入需要替换的HttpClient,可以选择Volley也可以选择OkHttp,我们使用Okhttp,在Module的build.gradle文件中配置

dependencies {    compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'    compile 'com.squareup.okhttp3:okhttp:3.3.1'    or    compile 'com.github.bumptech.glide:volley-integration:1.4.0@aar'    compile 'com.mcxiaoke.volley:library:1.0.8'}

这个版本具体选择多少,可以在https://github.com/bumptech/glide/wiki/Integration-Libraries这里查询到
Step2:
在AndroidMainfest.xml文件中写入

 <meta-data         android:name="com.bumptech.glide.integration.okhttp3.OkHttpGlideModule"            android:value="GlideModule"/>

你可能会有和我一样的疑问,Glide可以通过在配置清单里面配置
能不能写几个meta-data标签,一个标签里面配置一点参数
经过测试,发现这样做也是可以的。但是如果是同一种配置信息,比如你集成了OkHttp,又写一个标签集成Volley,最后一个会把前面的覆盖掉。

0 0
原创粉丝点击