Android 百度面试Evenbus3.0源码解析 3分钟手写最牛框架 看完成大神
https://blog.csdn.net/WHB20081815/article/details/88618798
Android 阿里面试OkHttp源码解析 最牛框架 看完成大神
https://blog.csdn.net/WHB20081815/article/details/88618460
2.Glide4.0特性
3.Glide的缓存机制
4.Glide的回调与监听
5.Glide强大的图片变换功能
6.Glide修改配置
7.Glide封装okhttp 添加下载进度
8.Glide和其他图片加载框架的优缺点比较
源码解析:
Glide最基本的用法就是三步走,先with(),再load(),最后into()
总结:得到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,那么只有当应用程序被杀掉的时候,图片加载才会停止。
总结;最终load()方法返回的其实就是一个DrawableTypeRequest对象
如果说前面两步都是在准备开胃小菜的话,那么现在终于要进入主菜了,因为into()方法也是整个Glide图片加载流程中逻辑最复杂的地方。
Glide的缓存功能,大部分都是在load()方法中进行的
load()也有很多重载的方法,它可以加载网络图片,本地图片,gif(动态图)图,Uri,File,
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);
得到不同的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
boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model,
Target
return false;
}
})
.into(imageView);
}
颜色,尺寸,滤镜的修改
Glide.with(this) .load(url) .transform(new CircleCrop(this)) .into(imageView);
把缓存的默认路径相关修改
String url = "http://guolin.tech/book.png";
Glide.with(this)
.load(url)
.skipMemoryCache(true)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(imageView);
---------------------
我们知道了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
public static class Factory implements ModelLoaderFactory
private final ModelCache
@Override
public ModelLoader
return new HttpUrlGlideUrlLoader(modelCache);
}
@Override
public void teardown() {
}
}
实现下载进度监听
那么,将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;
}
}