Gilde小结

by hzwusibo  20190504


优点:

支持gif

链式调用 (  编程性强、  可读性强  、 代码简洁)

glide三级缓存

Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。

对象池的使用生命周期绑定:图片的加载任务会与activity或者Fragment的生命周期绑定,当界面执行onStop的使用自动暂定,而当执行onStart的时候又会自动重新开启,同样的,动态Gif图的加载也是如此,以用来节省电量,

同时Glide会对网络状态做监听,当网络状态发生改变时,会重启失败的任务,以减少任务因网络连接问题而失败的概率。

预览图的使用

Q1:看过Glide源码吗,你印象最深的是什么?

Glide的缓存设计非常先进,考虑的场景也很周全。在缓存上Glide 分成了两个模块,一个是内存缓存,一个是硬盘缓存。

这两个缓存模块的作用各不相同,内存缓存的主要作用是防止应用重复将图片数据读取到内存当中,而硬盘缓存的主要作用是防止应用重复从网络或其他地方重复下载和读取数据。

Q2:简单说一下Glide的三级缓存?

Glide缓存机制大致分为三层:内存缓存、弱引用缓存、磁盘缓存。

存的顺序是:弱引用、内存、磁盘

取的顺序是:内存、弱引用、磁盘

Q3: glide三级缓存,glide加载一个一兆的图片(100*100),是否会压缩后再加载,放到一个200*200的view上会怎样,1000*1000呢,图片会很模糊,怎么处理?

而使用Glide,我们不用担心图片内存浪费,内存溢出的问题。因为Glide不会直接将图片的完整尺寸全部加载到内存中,而是用多少加载多少。Glide会自动判断ImageView的大小,然后只将这么大的图片像素加载到内存当中,帮助我们节省内存开支。

安卓图片显示的质量配置主要分为四种:

ARGB_8888 :32位图,带透明度,每个像素占4个字节

ARGB_4444 :16位图,带透明度,每个像素占2个字节

RGB_565 :16位图,不带透明度,每个像素占2个字节

ALPHA_8 :32位图,只有透明度,不带颜色,每个像素占4个字节

Glide的默认质量则为 RGB_565

Picasso的默认质量是 ARGB_8888 

Glide也并没有使用什么神奇的魔法,它内部的实现原理其实就是insmaplesize技术,

Android高效加载大图、多图解决方案,有效避免程序OOM

https://blog.csdn.net/guolin_blog/article/details/9316683

inSampleSize优化

https://www.jianshu.com/p/f15cd2ed6ec0

一个可选的BitmapFactory.Options参数,将这个参数的inJustDecodeBounds属性设置为true就可以让解析方法禁止为bitmap分配内存,返回值也不再是一个Bitmap对象,而是null。虽然Bitmap是null了,但是BitmapFactory.Options的outWidth、outHeight和outMimeType属性都会被赋值。

inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。例如,当inSampleSize为2时,一个20001000的图片,将被缩小为1000500,相应地,它的像素数和内存占用都被缩小为了原来的1/4:

Glide VS Picasso

不仅仅是 Google的推荐,支持 GIF 。 在没有 Glide 之前,常用的做法就是写了个自定义 view 然后 用一个 media 去播放。有了 Glide 之后可以像普通图片那样去加载并且显示出来动图。

Glide VS fresco

fresco 最大只支持图片文件大小为 2M 。有时候大的时候,  Glide 正常显示, fresco显示黑屏。。。

fresco 更多是native实现。所以需要对NDK有所了解,,相比较于 Glide, 同样遇到问题之后,修改源码的成本,Glide 更方便。

Glide VS Android-Universal-Image-Loader

已经不再维护的开源库,

Android碎片化那么严重,我们自己维护起来还是要考虑成本的。所以 Glide 胜出。 

Glide 支持功能更多。 比如 BitmapTransformation,比如圆形,圆角等。

更多变换

在图片组件中我实现了三种自定义变换,包含圆形,圆角和模糊。

网上也有很多Glide的图片变换开源库,我感觉做的最好的是glide-transformations这个库了吧。它实现了很多通用的图片变换效果,如裁剪变换、颜色变换、模糊变换等等,使得我们可以非常轻松地进行各种各样的图片变换。不过我们用不到那么多功能的话也不需要依赖一个三方库了吧,主要还是要学习为主。

Glide 是如何解决图片加载生命周期的?

Glide 的使用方式上,一定需要传入一个 context 给它。可以根据不同的上下文进行处理,拿到 context (除了application context)之后,Glide做了一件很巧妙的事情,就是在这个界面上追加一个 fragment,由于 fragment 添加到了 activity 上,是可以捕获到生命周期的,因此可以在 destroy 的时候取消掉当前context下的 glide对象中的加载任务。

Glide 坑爹的 wrap_content 不支持的问题

官方说了的,不支持并且不建议imageview设置wrap_content。因为这样 glide 不知道要加载多大的图片给我们才好。  普通的imageview其实也还好,如果放在列表(RecyclerView)中,  由于我们并不知道目标图片大小是多大的,所以我们选择了wrap_content,那么在上下来回滚动过程中,就会导致图片一会大一会小的bug.

Glide Module自定义缓存

图片框架中很多自定义的实现,而缓存也是框架中最为常见的行为之一。因此在开发使用中有些项目需求不凡试下自定义Glide的缓存.

https://blog.csdn.net/qq_38859786/article/details/80291476

源码解析

1,Glide采用的是三级缓存,内存–>磁盘–>网络

Glide的缓存功能,大部分都是在load()方法中进行的

 A:内存缓存的主要作用 :    是防止应用重复将图片数据读取到内存当中,

 B:磁盘缓存的主要作用 :   是防止应用重复从网络或其他地方重复下载和读取数据。

 C:Glide内存缓存的实现使用的LruCache算法。结合弱引用的机制,共同完成了内存缓存功能

3,Glide.with()

     With方法有5个重载的构造方法,运行你在activity,frgament或者其他地方使用.得到一个RequestManager对象 ,RequestManager实现了LifeCycleListener接口,绑定Activity/Fragment生命周期,对请求进行暂停,恢复,清除操作.

下面是5个构造方法

//RequestManager实现了LifeCycleListener接口

public static RequestManager with(Context context) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(context);

}

public static RequestManager with(Activity activity) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(activity);

}

public static RequestManager with(FragmentActivity activity) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(activity);

}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

public static RequestManager with(android.app.Fragment fragment) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(fragment);

}

//V4包的fragment

public static RequestManager with(Fragment fragment) {

    RequestManagerRetriever retriever = RequestManagerRetriever.get();

    return retriever.get(fragment);

}




3.1RequestManage对象源码

public class RequestManager implements LifecycleListener {

    private final Context context;

    private final Lifecycle lifecycle;

    private final RequestManagerTreeNode treeNode;

    private final RequestTracker requestTracker;

    private final Glide glide;

    public RequestManager(Context context, Lifecycle lifecycle, RequestManagerTreeNode treeNode) {

        this(context, lifecycle, treeNode, new RequestTracker(), new ConnectivityMonitorFactory());

    }

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,

                  RequestTracker requestTracker, ConnectivityMonitorFactory factory) {

        this.context = context.getApplicationContext();

        this.lifecycle = lifecycle;

        this.treeNode = treeNode;

        this.requestTracker = requestTracker;

        //通过Glide的静态方法获取实例对象,Glide是通过单利创建的

    this.glide = Glide.get(context);

        this.optionsApplier = new OptionsApplier();



4,load(url)

Glide的缓存功能,大部分都是在load()方法中进行的

load()也有很多重载的方法,它可以加载网络图片,本地图片,gif(动态图)图,Uri,File,

public DrawableTypeRequest<String> load(String string) {

    return (DrawableTypeRequest<String>) fromString().load(string);

}

//加载Uri

public DrawableTypeRequest<Uri> load(Uri uri) {

    return (DrawableTypeRequest<Uri>) fromUri().load(uri);

}

//加载File

public DrawableTypeRequest<File> load(File file) {

    return (DrawableTypeRequest<File>) fromFile().load(file);

}

//直接加载图片资源id,  R.mipmap.ic_launcher

public DrawableTypeRequest<Integer> load(Integer resourceId) {

    return (DrawableTypeRequest<Integer>) fromResource().load(resourceId);

}

//加载URL

@Deprecated

public DrawableTypeRequest<URL> load(URL url) {

    return (DrawableTypeRequest<URL>) fromUrl().load(url);

}




5,Glide的into()方法


public Target<TranscodeType> into(ImageView view) {

    Util.assertMainThread();

    if (view == null) {

        throw new IllegalArgumentException("You must pass in a non null View");

    }

    if (!isTransformationSet && view.getScaleType() != null) {

        switch (view.getScaleType()) {

            case CENTER_CROP:

                applyCenterCrop();

                break;

            case FIT_CENTER:

            case FIT_START:

            case FIT_END:

                applyFitCenter();

                break;

            //$CASES-OMITTED$

            default:

                // Do nothing.

        }

    }

    return into(glide.buildImageViewTarget(view, transcodeClass));

}

最终调用的into方法

//Target我们可以理解成View,只是Glide对我们的View做了一层封装。

public <Y extends Target<TranscodeType>> Y into(Y target) {

    //判断是否在主线程,(UI界面更新只能在主线程),不在主线程就报异常

    Util.assertMainThread();

    if (target == null) {

        throw new IllegalArgumentException("You must pass in a non null Target");

    }

    if (!isModelSet) {

        throw new IllegalArgumentException("You must first set a model (try #load())");

    }

    //获取request对象

    Request previous = target.getRequest();

    //requestTracker是请求跟踪类对象,主要管理请求的发起,暂停,清除

    if (previous != null) {

        previous.clear();

        requestTracker.removeRequest(previous);

        previous.recycle();

    }

    //创建request对象

    Request request = buildRequest(target);

    target.setRequest(request);

    //将target加入lifecycle,绑定生命周期

    lifecycle.addListener(target);

    //执行请求

    requestTracker.runRequest(request);

    return target;

Android图片加载框架最全解析(一),Glide的基本用法

https://blog.csdn.net/guolin_blog/article/details/53759439

Android图片加载框架最全解析(二),从源码的角度理解Glide的执行流https://blog.csdn.net/guolin_blog/article/details/53939176

Android图片加载框架最全解析(五),Glide强大的图片变换功能

https://blog.csdn.net/guolin_blog/article/details/71524668

Android图片加载框架最全解析(七),实现带进度的Glide图片加载功能

https://blog.csdn.net/guolin_blog/article/details/78357251

磁盘缓存

//DiskCacheStrategy.SOURCE:缓存原始数据,

// DiskCacheStrategy.RESULT:缓存变换后的资源数据,

// DiskCacheStrategy.NONE:什么都不缓存,

DiskCacheStrategy.ALL:缓存SOURC和RESULT。

  // 默认采用DiskCacheStrategy.RESULT策略

Glide会为每种大小的ImageView缓存一次。尽管一张图片已经缓存了一次,但是假如你要在另外一个地方再次以不同尺寸显示,需要重新下载,调整成新尺寸的大小,然后将这个尺寸的也缓存起来。具体说来就是:假如在第一个页面有一个200x200的ImageView,在第二个页面有一个100x100的ImageView,这两个ImageView本来是要显示同一张图片,却需要下载两次;可以通过改变Glide的行为让它即加载全尺寸图片,也加载不同尺寸图片

Glide.with(this) 

.load("http://nuuneoi.com/uploads/source/playstore/cover.jpg") 

.diskCacheStrategy(DiskCacheStrategy.ALL) 

.into(ivImgGlide); 

下次在任何ImageView中加载图片的时候,全尺寸的图片将从缓存中取出,重新调整大小,然后缓存。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容