美文网首页移动开发AndroidAndroid
Google推荐——Glide使用详解

Google推荐——Glide使用详解

作者: MrTrying | 来源:发表于2017-07-10 14:11 被阅读40845次
    Glide Logo

    零、前言

    本文所使用的Glide版本为3.7.0

    「推荐」设计模式系列

    设计模式(零)- 面向对象的六大原则
    设计模式(一)- 单例模式
    设计模式(二)- Builder模式
    设计模式(三)- 原型模式
    设计模式(四)- 工厂模式
    设计模式(五)- 策略模式
    设计模式(六)- 状态模式
    设计模式(七)- 责任链模式
    设计模式(八)- 解释器模式
    设计模式(九)- 命令模式
    设计模式(十)- 观察者模式
    设计模式(十一)- 备忘录模式
    设计模式(十二)- 迭代器模式
    持续更新中...

    一、简介

    Glide,一个被google所推荐的图片加载库,作者是bumptech。这个库被广泛运用在google的开源项目中,包括2014年的google I/O大会上发布的官方app。(PS:众所周知的简介就到此为止了)

    Glide 对于 Android SDK 的最低要求是 API level 10

    Glide滑行的意思,可以看出这个库的主旨就在于让图片加载变的流畅。现在被广泛使用,当然还是有很多开发者使用Square公司的picasso,也有两个库的对比

    原文链接:http://inthecheesefactory.com/blog/get-to-know-glide-recommended-by-google/en

    译文链接:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2650.html

    二、使用

    (一)导入

    在AndroidStudio上添加依赖非常简单

    dependencies {  
        compile 'com.github.bumptech.glide:glide:3.7.0'  
        compile 'com.android.support:support-v4:23.2.1'  
    }  
    

    Glide 也支持 Maven 项目形式:

    <dependency>
      <groupId>com.github.bumptech.glide</groupId>
      <artifactId>glide</artifactId>
      <version>3.7.0</version>
    </dependency>
    <dependency>
      <groupId>com.google.android</groupId>
      <artifactId>support-v4</artifactId>
      <version>r7</version>
    </dependency>
    

    如果是Eclipse使用去下载Glide的jar在项目中使用就可以了,jar的链接https://github.com/bumptech/glide/releases

    (二)基础使用

    基本方法

    Glide的一个完整的请求至少需要三个参数,代码如下:

    String url = "http://img1.dzwww.com:8080/tupian_pl/20150813/16/7858995348613407436.jpg";
    ImageView imageView = (ImageView) findViewById(R.id.imageView);
    Glide.with(context)
        .load(url)
        .into(imageView);
    
    • with(Context context) - 需要上下文,这里还可以使用 Activity、FragmentActivity、android.support.v4.app.Fragment、android.app.Fragment 的对象。将 Activity/Fragment 对象作为参数的好处是,图片的加载会和 Activity/Fragment 的生命周期保持一致,例如:onPaused 时暂停加载,onResume 时又会自动重新加载。所以在传参的时候建议使用 Activity/Fragment 对象,而不是 Context。
    • load(String url) - 这里我们所使用的一个字符串形式的网络图片的 URL,后面会讲解 load() 的更多使用方式
    • into(ImageView imageView) - 你需要显示图片的目标 ImageView

    占位图设置

    偶尔出现图片加载慢或者加载不出来的情况是难以避免的,所以为了 UI 能好看一些,我们会使用占位图。Glide 也为我们提供这种方法 placeHolder() 和 error()

    String url = "http://img1.dzwww.com:8080/tupian_pl/20150813/16/7858995348613407436.jpg";
    ImageView imageView = (ImageView) findViewById(R.id.imageView);
    Glide.with(context)
        .load(url)
        .placeholder(R.drawable.place_image)//图片加载出来前,显示的图片
        .error(R.drawable.error_image)//图片加载失败后,显示的图片
        .into(imageView);
    

    注:这里需要注意一点,placeholder() 和 error() 的参数都是只支持 int 和 Drawable 类型的参数,这种设计应该是考虑到使用本地图片比网络图片更加合适做占位图。

    缩略图

    Glide 的缩略图功能在这里不得不说,和占位图略有不同,占位图必须使用资源文件才行,而缩略图是动态的占位图可以从网络中加载。缩略图会在世纪请求加载完成或者处理完之后才显示。在原始图片到达之后,缩略图不会取代原始图片,只会被抹除。

    Glide 为缩略图提供了2种不同的加载方式,比较简单的方式是调用 thumbnail() 方法,参数是 float 类型,作为其倍数大小。例如,你传入 0.2f 作为参数,Glide 将会显示原始图片的20%的大小,如果原图是 1000x1000 的尺寸,那么缩略图将会是 200x200 的尺寸。为缩略图明显比原图小得多,所以我们需要确保 ImageView 的 ScaleType 设置的正确。

    Glide.with( context )
        .load( url )
        .thumbnail( 0.2f )
        .into( imageView );
    

    注:应用于请求的设置也将应用于缩略图。

    使用 thumbnail() 方法来设置是简单粗暴的,但是如果缩略图需要通过网络加载相同的全尺寸图片,就不会很快的显示了。所以 Glide 提供了另一种防止去加载缩略图,先看代码

    private void loadImageThumbnailRequest(){
        // setup Glide request without the into() method
        DrawableRequestBuilder<String> thumbnailRequest = Glide.with( context ).load( url );
        // pass the request as a a parameter to the thumbnail request
        Glide.with( context )
            .load( url )
            .thumbnail( thumbnailRequest )
            .into( imageView );
    }
    

    与第一种方式不同的是,这里的第一个缩略图请求是完全独立于第二个原始请求的。该缩略图可以是不同的资源图片,同时也可以对缩略图做不同的转换,等等...

    动画开关

    动画效果可以让图片加载变得更加的平滑,crossFade() 方法强制开启 Glide 默认的图片淡出淡入动画,当前版本3.7.0是默认开启的。crossFade() 还有一个重载方法 crossFade(int duration)。可以控制动画的持续时间,单位ms。动画默认的持续时间是300ms。既然可以添加动画,那肯定就可以设置没有任何淡出淡入效果,调用 dontAnimate()

    Glide.with(context)
        .load(url)
        .crossFade()//或者使用 dontAnimate() 关闭动画
        .placeholder(R.drawable.place_image)
        .error(R.drawable.error_image)
        .into(imageView);
    

    PS:Glide 是可以自定义动画效果的,这个在后面会讲解

    图片大小与裁剪

    在项目开发过程中,指定图片显示大小长长可能用到,毕竟从服务器获取的图片不一定都是符合设计图的标准的。我们在这里就可以使用 override(width,height) 方法,在图片显示到 ImageView 之前,重新改变图片大小。

    Glide.with(context)
        .load(url)
        .override(width,height)//这里的单位是px
        .into(imageView);
    

    在设置图片到 ImageView 的时候,为了避免图片被挤压失真,ImageView 本身提供了 ScaleType 属性,这个属性可以控制图片显示时的方式,具体的属性使用还是去搜索吧!Glide 也提供了两个类似的方法 CenterCrop() 和 FitCenter(),CenterCrop() 方法是将图片按比例缩放到足矣填充 ImageView 的尺寸,但是图片可能会显示不完整;而 FitCenter() 则是图片缩放到小于等于 ImageView 的尺寸,这样图片是显示完整了,但是 ImageView 就可能不会填满了。

    注:其实 Glide 的 CenterCrop() 和 FitCenter() 这两个方法分别对应 ImageView 的 ScaleType 属性中的 CENTER_CROP 和 FIT_CENTER 命名基本一致。

    图片的缓存处理

    为了更快的加载图片,我们肯定希望可以直接拿到图片,而不是进行网络请求,所以我们需要缓存。Glide 通过使用默认的内存和磁盘缓存来避免不必要的网络请求,之后我们再详细的去看它的实现。

    内存缓存

    内存缓存是 Glide 默认帮我们做了的,除非你不需要,可以调用 skipMemoryCache(true) 告诉 Glide 跳过内存缓存。这样 Glide 就不会把这张图片放到内存缓存中,该方法只影响内存缓存。(不要问调用skipMemoryCache(false)的问题,Glide 是默认将图片放入内存缓存中的)

    磁盘缓存

    磁盘缓存也是默认开启的,当然也是可以关闭的,不过关闭的方式略微有点不一样。

    Glide.with(context)
        .load(url)
        .skipMemoryCache(true)
        .diskCacheStrategy( DiskCacheStrategy.NONE )
        .into(imageView);
    

    上面这段代码将内存缓存和磁盘缓存都禁用了,这里使用枚举 DiskCacheStrategy.NONE 将磁盘缓存禁用了,这里涉及到了自定义磁盘缓存行为,我们接下来就讲解这个。

    自定义磁盘缓存行为

    使用 DiskCacheStrategy 可以为 Glide 配置磁盘缓存行为。Glide 的磁盘缓存比较复杂,这也是在图片加载可以比 Picasso 的原因(之一)。Picasso 只缓存了全尺寸的图片,而 Glide 的不同之处在于,Glide 不仅缓存了全尺寸的图,还会根据 ImageView 大小所生成的图也会缓存起来。比如,请求一个 800x600 的图加载到一个 400x300 的 ImageView 中,Glide默认会将这原图还有加载到 ImageView 中的 400x300 的图也会缓存起来。

    DiskCacheStrategy 的枚举意义:

    • DiskCacheStrategy.NONE 什么都不缓存
    • DiskCacheStrategy.SOURCE 只缓存全尺寸图
    • DiskCacheStrategy.RESULT 只缓存最终的加载图
    • DiskCacheStrategy.ALL 缓存所有版本图(默认行为

    这只是举个例子而已

    Glide.with(context)
        .load(url)
        .diskCacheStrategy( DiskCacheStrategy.SOURCE )
        .into(imageView);
    

    图片请求的优先级

    同一时间加载多个图片,App 将难以避免这种情况。如果这个时候我们希望用户的体验更好,往往会选择先加载对于用户更加重要的图片。Glide 可以调用 .priority() 方法配合 Priority 枚举来设置图片加载的优先级。

    //设置 HIGH 优先级
    Glide.with( context )
        .load( highPriorityImageUrl )
        .priority (Priority.HIGH )
        .into( imageView );
    //设置 LOW 优先级
    Glide.with( context )
        .load( lowPriorityImageUrl )
        .priority( Priority.LOW )
        .into( imageView );
    
    • Priority.LOW
    • Priority.NORMAL
    • Priority.HIGH
    • Priority.IMMEDIAT

    这里有一点需要注意,优先级并不是完全严格遵守的。Glide 将会用他们作为一个准则,尽可能的处理这些请求,但是不能保证所有的图片都会按照所有要求的顺序加载。

    显示 Gif 和 Video

    显示 GIf 对于 Glide 来说一个比较特别的功能(至少 Picasso 暂时还不行)而且使用起来非常简单

    String gifUrl = "http://i2.mhimg.com/M00/0E/AE/CgAAilTPWJ2Aa_EIACcMxiZi5xE299.gif";
    Glide.with( context )
        .load( gifUrl )
        .placeholder( R.drawable.default )
        .error( R.drawable.error )
        .into( imageView );
    

    这段代码还有点问题,如果加载的不是一张 gif 图的话,是没有办法显示的。

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

    做以上修改,如果图片类型不是 Gif 图的话就会当作 load 失败来处理,因此 error() 会被回调。即使这个url的图片是好的,也是不会显示的。当然,如果你想显示 Gif 但只是向现实静态的图片你就可以这么做

    Glide.with( context )
        .load( gifUrl )
        .asBitmap()
        .error( R.drawable.error )
        .into( imageView );
    

    仅仅是显示 Gif 的第一帧图像,这样就可以保证图片的正常显示了。

    还有一个神奇的功能,Glide 还能显示视频!But...只能够显示手机本地的视频,要是向现实网络上的视频的话,还是另寻他法吧!

    String filePath = "/storrage/emulated/0/Pictures/video.mp4";
    Glide.with( context )
        .load( Uri.fromFile( new File( filePath ) ) )
        .into( imageView );
    

    Glide 的基础使用就讲解到这了。

    (三)进阶使用

    Target篇

    到现在为止,我们所涉及到的代码都是直接加载图片到 ImageView 中。Glide 隐藏做了所有的网络请求和后台的线程处理,图片准备好之后切回到 UI 线程刷新 ImageView。也就是说 ImageView 在我们代码的链式结构中成为了最后一步,但是如果我们需要获取到 Bitmap 本身
    的话我们就需要用到 Target 了。Target 其实就是整个图片的加载的生命周期,所以我们就可以通过它在图片加载完成之后获取到 Bitmap。

    其实对于 Target 可以简单的理解为回调,本身就是一个 interface,Glide本身也为我们提供了很多 Target

    所有Targets
    SimpleTarget

    直接上代码

    private SimpleTarget<Bitmap> mSimpleTarget = new SimpleTarget<Bitmap>() {
        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> animation) {
            mImageView.setImageBitmap(resource);
        }
    };
    
    private void loadImageSimpleTarget() {
        Glide.with( thi s)
            .load( mUrl )
            .asBitmap()
            .into( mSimpleTarget );
    }
    

    首先创建了一个 SimpleTarget 的对象并且实现了 onResourceReady() 方法,看方法名能知道是图片加载完之后会调用该方法,参数就有我们需要的 Bitmap 。而使用 SimpleTarget 的对象的时候就像使用 ImageView 一样,作为参数传给 into() 方法就行了,Glide 会内部去处理并返回结果给任何一个对象。这里我们为了防止加载 Gif 、 Video 或者一些位置资源时与 mSimpleTarget 冲突,所以我们调用了 asBitmap() 方法,使其只能返回 Bitmap 对象。

    这里就有个问题了,如果我需要改变图片的大小怎么办?这点小问题 Glide 还是有考虑到的,加入原尺寸 1000x1000 的图片,我们显示的时候只需要是 500x500 的尺寸来节省时间和内存,你可以在 SimpleTarget 的回调声明中指定图片的大小。

    private SimpleTarget<Bitmap> mSimpleTarget = new SimpleTarget<Bitmap>(500,500) {
        @Override
        public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> animation) {
            mImageView.setImageBitmap(resource);
        }
    };
    

    从代码中可以看到 SimpleTarget 的对象的声明没有使用匿名对象,而是单独的声明了一个变量,这里是故意这么做的,如果使用匿名内部类的方式创建 SimpleTarget 的对象,这样会增大该对象在 Glide 完成图片请求之前就被回收的可能性。

    还记得前面说过 with() 方法传入 Activity 或者 Fragment 时 Glide 的图片加载会与他们的生命周期关联起来,但是如果我们使用 Target 的话,这个 Target 就有可能独立于他们的生命周期以外,这时候我们就需要使用 context.getApplicationContext() 的上下文了,这样只有在应用完全停止时 Glide 才会杀死这个图片请求。代码如下

    Glide.with(mContext.getApplicationContext())
            .load(mUrl)
            .asBitmap()
            .into(target);
    
    ViewTarget

    当我们使用 Custom View 时,Glide 并不支持加载图片到自定义 view 中的,使用 ViewTarget 更容易实现。

    public class CustomView extends FrameLayout {
        private ImageView mImageView;
    
        public CustomView(Context context) {
            super(context);
        }
    
        public CustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            mImageView = new ImageView(getContext());
            addView(mImageView , LayoutParams.MATCH_PARENT , LayoutParams.MATCH_PARENT);
        }
    
        public void setImage(Drawable drawable){
            mImageView.setImageDrawable(drawable);
        }
    }
    

    上面这个例子就没有办法直接使用 .into() ,如果我们使用 ViewTarget 实现呢!

    public void loadImageTarget(Context context){
        CustomView mCustomView = (CustomView) findViewById(R.id.custom_view);
    
        ViewTarget viewTarget = new ViewTarget<CustomView,GlideDrawable>( mCustomView ) {
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                this.view.setImage(resource);
            }
        };
    
        Glide.with(context)
                .load(mUrl)
                .into(viewTarget);
    }
    

    在 target 的 onResourceReady 回调方法中使用自定义 view 自己的方法去设置图片,可以看到在创建 ViewTarget 的时候传入了 CustomView 的对象。

    还有其他Target的使用这里就不一一讲述了,例如 AppWidgetTarget 、 NotificationTarget ...

    Transformations篇

    图片显示之前我们可能还需要对图片进行处理操作,比如:图片切圆角,灰阶处理等等;这些需求我们通过 Transformations 操作 bitmap 来实现,我们可以修改图片的任意属性:尺寸,范围,颜色,像素位置等等。其实我们之前已经提到过两个 Transformation 了,即 fitCenter 和 centerCrop ,这两个是 Glide 已经实现的。

    接下来就要讲讲怎么样来实现自己的 Transformation ,我们需要创建一个类去实现 Transformation 接口,但是要实现这个方法还是比较复杂的,接口中 transform 方法提供的参数 Resource<T> resource 不是那么好处理的。如果你只是想要对图片(不是 Gif 和 video)做常规的 bitmap 转换,我们推荐你使用抽象类 BitmapTransformation。它简化了很多的实现,这应该能覆盖 95% 的应用场景啦。

    下面的代码实现了对图片切圆角的操作,其中 getId() 方法描述了这个 Transformation 的唯一标识,为避免意外我们需要确保它是唯一的。

    public class RoundTransformation extends BitmapTransformation {
        private float radius = 0f;
    
        public RoundTransformation(Context context) {
            this(context, 4);
        }
    
        public RoundTransformation(Context context, int px) {
            super(context);
            this.radius = px;
        }
    
        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            return roundCrop(pool, toTransform);
        }
    
        private Bitmap roundCrop(BitmapPool pool, Bitmap source) {
            if (source == null)
                return null;
    
            Bitmap result = pool.get(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            if (result == null) {
                result = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
            }
    
            Canvas canvas = new Canvas(result);
            Paint paint = new Paint();
            paint.setShader(new BitmapShader(source, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
            paint.setAntiAlias(true);
            RectF rectF = new RectF(0f, 0f, source.getWidth(), source.getHeight());
            canvas.drawRoundRect(rectF, radius, radius, paint);
            return result;
        }
    
        @Override
        public String getId() {
            return getClass().getName() + Math.round(radius);
        }
    
    }
    

    现在我们有了自己的 Transformation 就可以来看看怎么使用了。

    调用 .transform() 方法,将自定义的 Transformation 的对象作为参数传递进去就可以使用你的 Transformation 了,这里也可以使用 .bitmaoTransform() 但是它只能用于 bitmap 的转换。

    Glide.with(context)
        .load(mUrl)
        .transform(new RoundTransformation(context , 20))
        //.bitmapTransform( new RoundTransformation(context , 20) )
        .into(mImageView);
    

    如果我们需要同时执行多个 Transformation 的话,我们不能使用链式的形式多次调用 .transform() 或 .bitmapTransform() 方法,即使你调用了,之前的配置就会被覆盖掉!我们可以直接传递多个转换对象给 .transform() 或 .bitmapTransform() 。

    Glide.with(context)
        .load(mUrl)
        .transform(new RoundTransformation(context , 20) ,  new RotateTransformation(context , 90f))
        .into(mImageView);
    

    这段代码中我们把一个图片切圆角,然后做了顺时针旋转90度处理。

    下面是旋转处理的代码

    public class RotateTransformation extends BitmapTransformation {
    
        private float rotateRotationAngle = 0f;
    
        public RotateTransformation(Context context, float rotateRotationAngle) {
            super( context );
            this.rotateRotationAngle = rotateRotationAngle;
        }
    
        @Override
        protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
            Matrix matrix = new Matrix();
    
            matrix.postRotate(rotateRotationAngle);
    
            return Bitmap.createBitmap(toTransform, 0, 0, toTransform.getWidth(), toTransform.getHeight(), matrix, true);
        }
    
        @Override
        public String getId() {
            return getClass().getName() + Math.round(rotateRotationAngle);
        }
    }
    

    注:这里需要注意一点 .centerCrop() 和 .fitCenter() 也都是 Transformation 所以也是遵循同时使用多个 Transformation 的规则的,即:当你使用了自定义转换后你就不能使用 .centerCrop() 或 .fitCenter() 了。

    这里有一个 GLide Transformations 的库,它提供了很多 Transformation 的实现,非常值得去看,不必重复造轮子对吧!
    glide-transformations
    这个库有两个不同的版本,扩展版本包含了更多的 Transformation ,它是通过设备的 GPU 来计算处理的,需要有额外的依赖,所以这两个版本的设置有一点不同。还是根据需要再决定使用那个版本吧!

    Animate篇

    从图像到图像的平滑过渡是非常重要,Glide 中有一个标准动画去柔软的在你的 UI 中改变,但是我们现在希望设置自己的动画。

    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true">
    
        <scale
            android:duration="@android:integer/config_longAnimTime"
            android:fromXScale="0.1"
            android:fromYScale="0.1"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toXScale="1"
            android:toYScale="1"/>
    </set>
    

    这是个 XML 动画缩放动画,图片刚开始小的,然后逐渐增大到原尺寸。我们现在要应用到 Glide 加载图片中去,调用 .animate() 方法传入 XML 动画的 id 即可。

    Glide.with(context)
        .load(mUrl)
        .transform(new RoundTransformation(this , 20))
        .animate( R.anim.zoom_in )
        .into(mImageView);
    

    这种加载方式用在常规的 ImageView 上是没有问题的,但如果使用的 Target 是一些自定义的时候就没法好好的实现了。这时候我们就可以通过传入实现了 ViewPropertyAnimation.Animator 接口的类对象来实现。

    ViewPropertyAnimation.Animator animator = new ViewPropertyAnimation.Animator() {
        @Override
        public void animate(View view) {
            view.setAlpha( 0f );
    
            ObjectAnimator fadeAnim = ObjectAnimator.ofFloat( view, "alpha", 0f, 1f );
            fadeAnim.setDuration( 2500 );
            fadeAnim.start();
        }
    };
    

    然后,我们只需要在 Glide 请求中设置这个动画对象就ok了

    Glide.with(context)
        .load(mUrl)
        .animate( animator )
        .into(viewTarget);
    

    在 animate(View view) 中你的动画对象方法中, 你可以做任何你想要对视图做的事情。自由的用你创建的动画吧。

    Modules篇

    Glide 的 Module 是一个可以全局改变 Glide 的行为的东西,为了定制 Glide 的行为我们要去实现 interface GlideModule 来写我们自己的代码。

    public class ExampleModule implements GlideModule{
        @Override
        public void applyOptions(Context context, GlideBuilder builder) {
            // todo
        }
    
        @Override
        public void registerComponents(Context context, Glide glide) {
            // todo
        }
    }
    

    可以看到 GlideModule 为我们提供了两个方法,这里我们主要使用的是 applyOptions(Context context, GlideBuilder builder) , 我们自己的需要重新定义的代码写在该方法里就可以了。然后我们还需要去 AndroidManifest.xml 中使用 meta 声明我们上面实现的 Module

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.mrtrying.demoglide">
    
        <application>
    
            <meta-data
                android:name="com.mrtrying.demoglide.module.ExampleModule"
                android:value="GlideModule" />
    
            ...
    
        </application>
    
        ...
    
    </manifest>
    

    到这里我们就完成了 ExampleModule 的声明,Glide 将会在工作是使用我们所定义的 Module

    TIPS

    • 我们需要将 android:name 属性改成 包名+类名 的形式,这样的引用才是正确的。如果你想删掉 Glide Module,只需要删除在 AndroidManifest.xml 中的声明就可以了。Java 类可以保存,说不定以后会用呢。如果它没有在 AndroidManifest.xml 中被引用,那它不会被加载或被使用。

    • 定制 module 的话 Glide 会有这样一个优点:你可以同时声明多个 Glide module。Glide 将会(没有特定顺序)得到所有的声明 module。因为你当前不能定义顺序,请确保定制不会引起冲突!

    这个过程走通了,接下来我们来看看是怎么自定义的。applyOptions(Context context, GlideBuilder builder) 中有两个参数, 我们通过使用 GlideBuilder 来实现我们的需求。先看看 GlideBuilder 中可用的方法

    • .setMemoryCache(MemoryCache memoryCache)
    • .setBitmapPool(BitmapPool bitmapPool)
    • .setDiskCache(DiskCache.Factory diskCacheFactory)
    • .setDiskCacheService(ExecutorService service)
    • .setResizeService(ExecutorService service)
    • .setDecodeFormat(DecodeFormat decodeFormat)

    可以看到,这个 GlideBuilder 对象给你访问了 Glide 重要的核心组件。接下来我们就要试着去使用这些方法

    增加 Glide 的图片质量

    在 Android 中有两个主要的方法对图片进行解码:ARGB_8888 和 RGB_565 。前者为每个像素使用4个字节,后者每个像素仅使用2个字节。ARGB_8888 的有时就是图像质量更高以及能储存一个 alpha 通道。 Picasso 使用的就是 ARGB_8888 , Glide 默认使用低质量的 RGB_565 ,但是现在你就可以使用 Glide module 来改变图片解码规则。就象这样

    public class QualityModule implements GlideModule{
        @Override
        public void applyOptions(Context context , GlideBuilder builder){
            builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888);
        }
    
        @Override
        public void registerComponents(Context context , Glide glide){
            // nothing to do here
        }
    }
    

    这样我们就简单的增加了 Glide 的图片质量。

    往往我们还会遇到一些情况,希望 Glide 可以使用我们自己的网络框架,我们就需要做一些事情来实现这个需求了。Glide 的开发者不强制设置网络库给你,所以Glide可以说和 HTTPS 无关。理论上,它可以与任何的网络库实现,只要覆盖了基本的网络能力就行。同样是需要实现 Glide 的 ModuleLoader 的接口,为了让我们更加易用,Glide 为 OkHttp 和 Volley 两个网络库提供了实现。

    假设我要集成 OkHttp 作为 Glide 的网络库,我可以手动实现一个 GlideModule 也可以在 build.gradle 中添加依赖:

    dependencies{
        //...
        
        // Glide
        compile 'com.github.bumptech.glide:glide:3.7.0'
    
        // Glide's OkHttp Integration
        compile 'com.github.bumptech.glide:okhttp-integration:1.4.0@aar'
        compile 'com.squareup.okhttp:okhttp:3.2.0'
    }
    

    Gradle 会自动合并必要的 GlideModule 到你的 AndroidManifest.xml , Glide 会认可在 manifest 中存在,然后使用 OkHttp 做到的所有网络连接。

    相关文章

      网友评论

      • 无尘粉笔:你好,这个添加依赖的方法在2018年底就要被取消了
        dependencies {
        compile 'com.github.bumptech.glide:glide:3.7.0'
        compile 'com.android.support:support-v4:23.2.1'
        }
        还有什么其他的方法吗
        MrTrying:你说的事gradle的语法么?如果是项目直接使用的话compile可以替换成implementation,如果在自己封装的library中使用可以替换成api
      • 我是你森哥哥:你好,我想请教一个问题 ,这个路径 http://nba.sports.qq.com/media/img/players/head/260x190/201935.png 我 用Glide加载图片的时候加载不出来,listener监听里边的Exception e是空的,不知道什么问题 ,但是我用Picasso和Fresco就可以加载出这张图片,困扰我 一天了这个问题,怎么试都加载不出来
        MrTrying:@我是你森哥哥 这么看确实是很简单的代码,没法定位问题
        我是你森哥哥:@MrTrying 这个我加载的代码 : Glide.with(this).load(url).into(iv_bg);没有设置别的属性啥的

        布局文件如下:

        <ImageView
        android:id="@+id/iv_bg"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true" />
        MrTrying:我测试了一下这个链接Glide显示是没有问题的,你是不是设置什么其他的一些东西?
      • Walke_Z:你好,请问Glide可以根据自定义key做缓存么?【情况:后台返回的图片全地址带有时间戳等参数。同一图片,不同时间,不同地址】
        MrTrying:@Walke_Z 你这是不需要比较实时的变化么?使用其他的做缓存是可以的,v3版本使用GlideGlide.with(context).using()方法可以自己单独定义Glide的加载方式,然后自己实现getResourceFetcher()方法,返回自定义的HttpCacheUrlFetcher对象,这里就可以使用固定的saveKey做文件名存储
        Walke_Z:@MrTrying 有个请情况:有一个轮播的广告图片列表List<BannerInfo>,BannerInfo中有两个参数一个是固定的saveKey,一个是会变动的imageUrl【其实就是在地址链接带有类似时间戳的参数,每次刷新列表后会变。】;Gilded可以用这个saveKey作为缓存key么?如果默认使用imageUrl做缓存key的,我这情况就起不到比较好缓存的效果了。
        MrTrying:@Walke_Z 自定义key具体是指什么?你说的情况,在glide的默认缓存中只要地址是不同的缓存就会是不一样的。难道你需要存成一样的?
      • 9df2a6e99159:如何拿到图片加载的进度并添加加载动画呢?类似微博那种
        MrTrying:我百度了一下,https://www.jianshu.com/p/548031c62257,这篇文章有v3版本的具体实现,你可以参考
        MrTrying:v4的版本的话,同样可以自己重写OkHttpStreamFetcher加载类来实现进度的回调,但是没有具体的实现方案。
        MrTrying:v3版本,理论上来说应该可以通过重写loader,自己重写网络过去图片的过程。如果是用okhttp的话,可以在读流的统计进度,拦截器应该也可以实现的。
      • nonfuxinyang:感谢作者分享,仔细看了一遍,获益良多。
        MrTrying:这是开发过程中得一些记录,分享出来也是希望可以帮助到他人:blush:
      • Try_a0af:Glide.with(mContext)
        .load(girl.url)
        .placeholder(R.drawable.bg_default)
        .into(holder.girlImage);
        大神你好,请问一下“Cannot resolve method‘placeholder(int)’”怎么解决?
        Try_a0af:@MrTrying 感谢。
        MrTrying:你用的是Glide v4的版本吧!v4 和 v3相差很大的,差别可以看下这个http://bumptech.github.io/glide/doc/migrating.html
      • android0226:内容很全,加上滑动处理就更好了
        MrTrying:Glide中有提供Glide.with(context).resumeRequests();和Glide.with(context).pauseRequests();方法回复暂停请求,可以在滑动状态改变的时候做相应的处理,不知道这个有没有解决你的问题
      • 梦里风吹过:Glide有没有圆形图片或者圆角图片这样的实现方法?
        MrTrying:@梦星Chen 原理还是操作图片,能否使用还是看你的使用场景
        梦里风吹过:@MrTrying 好的,谢谢你,回头有空研究一下
        MrTrying:@梦星Chen Glide没有自带实现图形变换,但是通过Glide提供的Transformation实现图形变换的需求

      本文标题:Google推荐——Glide使用详解

      本文链接:https://www.haomeiwen.com/subject/jrgyhxtx.html