专栏名称: 安卓开发精选
伯乐在线旗下账号,分享安卓应用相关内容,包括:安卓应用开发、设计和动态等。
目录
相关文章推荐
鸿洋  ·  一个大型 Android 项目的模块划分哲学 ·  2 天前  
stormzhang  ·  年底扣税变多了 ·  3 天前  
鸿洋  ·  细嗅蔷薇,Gradle 系列之 Task 必知必会 ·  3 天前  
stormzhang  ·  来自李子柒的压迫感 ·  4 天前  
鸿洋  ·  理解Android ... ·  4 天前  
51好读  ›  专栏  ›  安卓开发精选

Glide 不能说的秘密

安卓开发精选  · 公众号  · android  · 2016-08-26 08:08

正文

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - joe

链接:http://android.jobbole.com/84454/

点击 → 了解如何加入专栏作者


Glide简介


An image loading and caching library for Android focused on smooth scrolling

一个专注于流畅滑动的图片加载和缓存库


优势


其实现在,图片加载和缓存的库已经超级多了,Glide是目前谷歌官方推荐的加载库,它有一个比较牛的特点就是支持GIF格式的图片播放,目前的人气也超级高!!另外还可以设置渐变的加载效果,控制相关缓存策略等!以下就围绕这些做一些具体的介绍!


引入库


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'

}


如果你的网络请求底层使用了Okhttp的话,那么可以指定这个让Glide网络层使用Okhttp。


dependencies {

compile 'com.github.bumptech.glide:okhttp-integration:1.4.0@aar'

//compile 'com.squareup.okhttp:okhttp:2.2.0'

}

 

dependencies {

compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'

//compile 'com.squareup.okhttp3:okhttp:3.2.0'

}


配置这个话,还需要在AndroidManifest里面加入相关的配置:


meta-data

        android:name="com.bumptech.glide.integration.okhttp.OkHttpGlideModule"

        android:value="GlideModule" />


基本的加载


Glide.with(image.getContext())

                .load(imageUrl)

                .into(image);


在这个的基础之上,设置默认显示的图片,设置加载错误的图片,设置渐变效果.crossFade()来指定一个渐变的效果:


Glide.with(image.getContext())

                .load(imageUrl)        

                .error(R.mipmap.girl)

                .placeholder(R.mipmap.ic_launcher)

                .crossFade(R.anim.fade_out_rapidly, 5000)

                .into(image);


一般使用到这这里就差不多了吧,不过要是觉得Glide就这样了那可真的是太对不住Glide了!




进阶-缓存策略:


Glide默认会使用磁盘缓存和内存缓存的,你可以根据喜好和相关的使用场景定制相关的策略。


  • skipMemoryCache()跳过内存缓存,这个默认就是false。如果不需要就设置为true来确保不会缓存到内存中。


  • diskCacheStrategy() 磁盘缓存策略,Glide支持很多种图片缓存策略。


  • DiskCacheStrategy.RESOURCE 只缓存原始文件


  • DiskCacheStrategy.ALL 缓存所有size的图片和源文件


  • DiskCacheStrategy.RESULT 缓存最后的结果文件


  • DiskCacheStrategy.NONE 撒都不缓存


在V3的版本默认是DiskCacheStrategy.RESULT的策略。


进阶-转换


asBitmap() //总是将其转换为Bitmap的对象

asGif() //总是将其转换为gi的对象,但是如果它不是gif的,那么就会转换失败,所以最好要设置一个error()的对象


另外Glide提供了相关的方法,你可以自定义相关的 Transformation,来完成相关的转换!


这里一共有两个方法,一个是transform(),一个是getId(),如果说我们需要完成一些自己的需求,比如说,你需要加载出圆形的图片,这里简单有效的方法就是直接设置一个CirCleTransform就好了:


public class CircleTransform extends BitmapTransformation {

 

    public CircleTransform(Context context) {

        super(context);

    }

 

    private static Bitmap circleCrop(BitmapPool pool, Bitmap source) {

        if (source == null) return null;

 

        int size = Math.min(source.getWidth(), source.getHeight());

        int x = (source.getWidth() - size) / 2;

        int y = (source.getHeight() - size) / 2;

 

        // TODO this could be acquired from the pool too

        Bitmap squared = Bitmap.createBitmap(source, x, y, size, size);

 

        Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888);

        if (result == null) {

            result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

        }

 

        Canvas canvas = new Canvas(result);

        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG | Paint

                .ANTI_ALIAS_FLAG);

        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader

                .TileMode.CLAMP));

        float r = size / 2f;

        canvas.drawCircle(r, r, r, paint);

        return result;

    }

 

    @Override

    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {

        return circleCrop(pool, toTransform);

    }

 

    @Override

    public String getId() {

        return getClass().getName();

    }

}


stackoverflow

http://stackoverflow.com/questions/25278821/how-do-rounded-image-with-glide-library/25806229#25806229


如果需要圆角矩形的话:


public class RoundTransform extends BitmapTransformation {

    private int cornerRadius;

    private RectF rectF = new RectF();

 

    /**

     * @param round dp

     */

    public RoundTransform(Context context,int round) {

        super(context);

        float density = context.getResources().getDisplayMetrics().density;

        this.cornerRadius = (int) (round/density+0.5f);

    }

 

    private  Bitmap circleCrop(BitmapPool pool, Bitmap source) {

        if (source == null) return null;

        int width = source.getWidth();

        int height = source.getHeight();

        rectF.set(0, 0, width, height);

 

 

        Bitmap squared = Bitmap.createBitmap(source, 0, 0, width, height);

 

        Bitmap result = pool.get(width, height, Bitmap.Config.ARGB_8888);

        if (result == null) {

            result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        }

 

        Canvas canvas = new Canvas(result);

        Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG | Paint

                .ANTI_ALIAS_FLAG);

        paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader

                .TileMode.CLAMP));

        canvas.drawRoundRect(rectF, cornerRadius, cornerRadius, paint);

        return result;

    }

 

    @Override

    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {

        return circleCrop(pool, toTransform);

    }

 

    @Override

    public String getId() {

        return getClass().getName();

    }

}


Glide还为我们提供了CenterCropFitCenter等转换器,这些我们都可以直接使用!

这里的getId()返回的必须是唯一的字符串


说白了,我们这里可以做很多的操作的,因为我们已经拿到相关的对象,可以随意的进行各种旋转、平移、放大、高斯模糊等。


Glide 转换集合 已经给我们尽可能提过了足够的转换!

https://github.com/wasabeef/glide-transformations


所以,还去引入什么CircleImageView什么的,真的就可以考虑考虑了,简直弱爆了!一个Transform直接搞定。


进阶-相关回调


RequestListenerString, GlideDrawable>() {

                @Override

                public boolean onException(Exception e, String model, Target target, boolean isFirstResource) {

                    return false;

                }

 

                @Override

                public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) {

                    return false;

                }


onResourceReady()当资源加载成功之后,会走这个回调。


onException() 当加载异常时,会走这个回调。


进阶-各种Target


Glide.with(getApplicationContext())

            .load(imageUrl)

            .into(mTarget);


如果需要给自定义View加载对应的图片,因为Glide根本不知道图片需要加载到那个具体的View上面去展示,那这个就需要使用Glide为我们提供的相关接口,自己去实现就好了。


比如我们这里有一个自定义的FrameLayout,名字就叫MyFrameLayout,里面有一个TextView和一个ImageView,

对外提供一个方法:


public void setimage(Drawable current) {

    imageView.setBackground(current);

}


然后自定义一个ViewTarget:


public class MyViewTarget extends ViewTargetMyFrameLayout, GlideDrawable> {

        public MyViewTarget(MyFrameLayout view) {

            super(view);

 

        }

 

        @Override

        public void onResourceReady(GlideDrawable resource, GlideAnimation? super GlideDrawable> glideAnimation) {

            this.view.setImage(resource.getCurrent());

 

        }

    }

 

`Glide`已经针对一些特殊情况制定了一些适合的Target,比如说通知栏相关的创建,`NotificationTarget`这些我们都可以直接获取使用。


进阶-定制各种策略


我们可以通过GlideMode来定制相关的策略,比如说磁盘缓存,内存缓存,加载图片使用的编码等!

 

    public class GlideConfiguration implements GlideModule {

 

    @Override

    public void applyOptions(Context context, GlideBuilder builder) {

        // Prefer higher quality images unless we're on a low RAM device

        MemorySizeCalculator calculator = new MemorySizeCalculator(context);

        int defaultMemoryCacheSize = calculator.getMemoryCacheSize();

        int defaultBitmapPoolSize = calculator.getBitmapPoolSize();

 

        int customMemoryCacheSize = (int) (1.2 * defaultMemoryCacheSize);

        int customBitmapPoolSize = (int) (1.2 * defaultBitmapPoolSize);

 

        //1、内存缓存相关

        builder.setMemoryCache(new LruResourceCache(customMemoryCacheSize));

        builder.setBitmapPool(new LruBitmapPool(customBitmapPoolSize));

 

        // set size & external vs. internal

        int cacheSize100MegaBytes = 104857600;

        //2、磁盘缓存相关

        builder.setDiskCache(

//                new InternalCacheDiskCacheFactory(context, cacheSize100MegaBytes)//内部使用的磁盘缓存区

                new ExternalCacheDiskCacheFactory(context, cacheSize100MegaBytes)//外部可以访问的磁盘缓存区

 

        );

 

 

        ActivityManager activityManager =

                (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

        //3、根据运行内存情况,自定义对图像的编码格式

        builder.setDecodeFormat(activityManager.isLowRamDevice() ?

                        DecodeFormat.PREFER_RGB_565 : DecodeFormat.PREFER_ARGB_8888);

    }

 

    @Override

    public void registerComponents(Context context, Glide glide) {

 

    }

}


记得要在AndroidManifiest里面配置相关的参数:


meta-data

            android:name="io.plaidapp.util.glide.GlideConfiguration"

            android:value="GlideModule" />


总结


青出于蓝胜于蓝,Glide就是在Picasso的基础上改进出来的,有着相似的调用方法!作为新秀,增加的Gif的支持可以说是它的新的优势!丰富的缓存策略也更能满足开发需求。

要看Glide运用项目的话,推荐Plaid,保证你有收获!