Android 腾讯面试Glide源码解析 3分钟手写最牛框架 看完成牛逼哄哄

Android 腾讯面试Glide源码解析 3分钟手写最牛框架 看完成牛逼哄哄

https://blog.csdn.net/WHB20081815/article/details/88619371

Android 百度面试Evenbus3.0源码解析 3分钟手写最牛框架 看完成大神

https://blog.csdn.net/WHB20081815/article/details/88618798

Android 阿里面试OkHttp源码解析 最牛框架 看完成大神

https://blog.csdn.net/WHB20081815/article/details/88618460

1.Glide基本使用

2.Glide4.0特性

3.Glide的缓存机制

4.Glide的回调与监听

5.Glide强大的图片变换功能

6.Glide修改配置

7.Glide封装okhttp 添加下载进度

8.Glide和其他图片加载框架的优缺点比较

Glide.with(this).load(url).into(imageView);

源码解析:

Glide最基本的用法就是三步走,先with(),再load(),最后into()

1. with()

总结:得到RequestManager

接下来我们看传入非Application参数的情况。不管你在Glide.with()方法中传入的是Activity、FragmentActivity、v4包下的Fragment、还是app包下的Fragment,最终的流程都是一样的,那就是会向当前的Activity当中添加一个隐藏的Fragment。具体添加的逻辑是在上述代码的第117行和第141行,分别对应的app包和v4包下的两种Fragment的情况。那么这里为什么要添加一个隐藏的Fragment呢?因为Glide需要知道加载的生命周期。很简单的一个道理,如果你在某个Activity上正在加载着一张图片,结果图片还没加载出来,Activity就被用户关掉了,那么图片还应该继续加载吗?当然不应该。可是Glide并没有办法知道Activity的生命周期,于是Glide就使用了添加隐藏Fragment的这种小技巧,因为Fragment的生命周期和Activity是同步的,如果Activity被销毁了,Fragment是可以监听到的,这样Glide就可以捕获这个事件并停止图片加载了

--------------------- 

首先,调用Glide.with()方法用于创建一个加载图片的实例。with()方法可以接收Context、Activity或者Fragment类型的参数。也就是说我们选择的范围非常广,不管是在Activity还是Fragment中调用with()方法,都可以直接传this。那如果调用的地方既不在Activity中也不在Fragment中呢?也没关系,我们可以获取当前应用程序的ApplicationContext,传入到with()方法当中。注意with()方法中传入的实例会决定Glide加载图片的生命周期,如果传入的是Activity或者Fragment的实例,那么当这个Activity或Fragment被销毁的时候,图片加载也会停止。如果传入的是ApplicationContext,那么只有当应用程序被杀掉的时候,图片加载才会停止。

2. load() 调用的是 RequestManager.load()

总结;最终load()方法返回的其实就是一个DrawableTypeRequest对象

3. into()

如果说前面两步都是在准备开胃小菜的话,那么现在终于要进入主菜了,因为into()方法也是整个Glide图片加载流程中逻辑最复杂的地方。

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

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

 

 

 

 

 

Glide的缓存机制

Glide又将它分成了两个模块,一个是内存缓存,一个是硬盘缓存。

Glide内存缓存的实现自然也是使用的LruCache算法。不过除了LruCache算法之外,Glide还结合了一种弱引用的机制,共同完成了内存缓存功能

可以看到,这里首先会将缓存图片从activeResources中移除,然后再将它put到LruResourceCache当中。

这样也就实现了正在使用中的图片使用弱引用来进行缓存,不在使用中的图片使用LruCache来进行缓存的功能。

这就是Glide内存缓存的实现原理。

Engine ----EngineResourceFactory-----EngineResource

缓存的计数机制

EngineResource是用一个acquired变量用来记录图片被引用的次数,调用acquire()方法会让变量加1,调用release()方法会让变量减1

硬盘缓存

首先,和内存缓存类似,硬盘缓存的实现也是使用的LruCache算法,而且Google还提供了一个现成的工具类DiskLruCache。

当然,Glide是使用的自己编写的DiskLruCache工具类,但是基本的实现原理都是差不多的。

decodeFromCache

 

Glide.with(this) .load(new MyGlideUrl(url)) .into(imageView);

玩转Glide的回调与监听

得到不同的listener(),可以自己封装

public void loadImage(View view) {

    String url = "http://cn.bing.com/az/hprichbg/rb/TOAD_ZH-CN7336795473_1920x1080.jpg";

    Glide.with(this)

            .load(url)

            .listener(new RequestListener() {

                @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;

                }

            })

            .into(imageView);

}

Glide强大的图片变换功能

颜色,尺寸,滤镜的修改

 

Glide.with(this) .load(url) .transform(new CircleCrop(this)) .into(imageView);

Glide修改配置

把缓存的默认路径相关修改 

String url = "http://guolin.tech/book.png";

Glide.with(this)

     .load(url)

     .skipMemoryCache(true)

     .diskCacheStrategy(DiskCacheStrategy.NONE)

     .into(imageView);

--------------------- 

Glide  自定义组件,把网络框架改成http

 

我们知道了Glide内部HTTP通讯组件的底层实现是基于HttpUrlConnection来进行定制的。但是HttpUrlConnection的可扩展性比较有限,我们在它的基础之上无法实现监听下载进度的功能,因此今天的第一个大动作就是要将Glide中的HTTP通讯组件替换成OkHttp。

首先来看一下Glide中目前有哪些组件吧,在Glide类的构造方法当中,如下所示:

 

public class Glide {

 

    Glide(Engine engine, MemoryCache memoryCache, BitmapPool bitmapPool, Context context, DecodeFormat decodeFormat) {

        ...

        register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.Factory());

        register(File.class, InputStream.class, new StreamFileLoader.Factory());

        register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());

        register(int.class, InputStream.class, new StreamResourceLoader.Factory());

        register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());

        register(Integer.class, InputStream.class, new StreamResourceLoader.Factory());

        register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory());

        register(String.class, InputStream.class, new StreamStringLoader.Factory());

        register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());

--------------------- 

register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());

 

public class HttpUrlGlideUrlLoader implements ModelLoader {

 

    private final ModelCache modelCache;

 

    public static class Factory implements ModelLoaderFactory {

        private final ModelCache modelCache = new ModelCache(500);

 

        @Override

        public ModelLoader build(Context context, GenericLoaderFactory factories) {

            return new HttpUrlGlideUrlLoader(modelCache);

        }

 

        @Override

        public void teardown() {

        }

    }

实现带进度的Glide图片加载功能

实现下载进度监听

 

那么,将HTTP通讯组件替换成OkHttp之后,我们又该如何去实现监听下载进度的功能呢?这就要依靠OkHttp强大的拦截器机制了。

 

我们只要向OkHttp中添加一个自定义的拦截器,就可以在拦截器中捕获到整个HTTP的通讯过程,然后加入一些自己的逻辑来计算下载进度,这样就可以实现下载进度监听的功能了。

 

拦截器属于OkHttp的高级功能,不过即使你之前并没有接触过拦截器,我相信你也能轻松看懂本篇文章的,因为它本身并不难。

 

确定了实现思路之后,那我们就开始动手吧。首先创建一个没有任何逻辑的空拦截器,新建ProgressInterceptor类并实现Interceptor接口,代码如下所示:

 

public class ProgressInterceptor implements Interceptor { 

 

    @Override 

    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request(); 

        Response response = chain.proceed(request); 

        return response; 

    } 

 

}

你可能感兴趣的:(框架源码okhttp,evenbus,glide)