学习来源:郭霖大师博客地址
1、图片加载框架挺多,如Volley、Glide、Picasso、Fresco、本次是跟着郭大师学习Glide、做学习笔记。
2、首先添加Glide的依赖 compile 'com.github.bumptech.glide:glide:3.7.0';或者eclipse下载glide3.7的jar包地址
3、使用Glide需要获取网络权限:<uses-permission android:name="android.permission.INTERNET">
4、Glide的使用:
1.基本调用:Glide.with(this).load(url).into(imageView);
with方法可以传递Context、Activity、Fragment,ApplicationContext类型的参数,with方法中传递的参数决定了Glide加载图片的生命周期,如果传递的是Activity或者Fragment,那么此Activity或Fragment销毁时,图片加载会停止;如果传递的是ApplicationContext,那么只有程序停止时,图片加载会停止。
load方式支持加载各种各样的图片资源,包括网络图片,本地图片,应用资源,二进制流,Url对象等,对应有如下多个重载方式。
// 加载本地图片File file = new File(getExternalCacheDir() + "/image.jpg"); Glide.with(this).load(file).into(imageView);
// 加载应用资源int resource = R.drawable.image; Glide.with(this).load(resource).into(imageView);
// 加载二进制流byte[] image = getImageBytes(); Glide.with(this).load(image).into(imageView);
// 加载Uri对象Uri imageUri = getImageUri(); Glide.with(this).load(imageUri).into(imageView);
into方法传递的参数可以是ImageView的实例,也可以是其他类型的参数,后边学习。
2.占位图的使用
图片加载需要一定的时间,特别是第一次加载图片时,所以需要先给图片一个默认图片,即占位图,等图片加载完成后会被替换。
使用方法placeholder方法:Glide.with(this).load(url).placeholder(R.drawable.loading).into(imageView)。
3.异常占位图
图片加载可能存在失败的情况,所以需要设置一个异常占位图,在加载失败场景下显示。
使用error方法:Glide.with(this).load(url).placeholder(R.drawable.loading).error(R.drawable.error).into(imageView)。
4.指定图片的格式
Glide可以加载GIF图片,不需要特殊的设置,它会自行判断,所以使用上述的方式传入一个GIF的Url即可加载。
如果我们需要加载的就是一个静态图,不需要Glide自行判断,可以代码设置加载图片类型。
加载静态图片:Glide.with(this).load(url).asBitmap().... 如果实际传入的是GIF图片,那么会加载显示GIF图片的第一帧
加载动态图片:Glide.with(this).load(url).asGif()...... 如果实际传入的是静态图片,那么会加载失败,显示异常占位图
5.设置图片的大小
图片造成的内存浪费,图片的实际尺寸的像素大于ImageView所需要的像素尺寸。
使用Glide则不需要考虑内存的浪费,甚至是内存溢出的问题,Glide会自动判断ImageView的大小,加载合适的尺寸到内存中。
当然也可以设置加载图片的大小忽略ImageView的实际大小。使用方法override:Glide.with(this).load(uri).override(100,100)....。
6.源码地址
Glide的GitHub主页的地址是:https://github.com/bumptech/glide 这个看到的始终是最新的
Glide的3.7.0版本源码地址:https://github.com/bumptech/glide/tree/v3.7.0
7.Glide缓存
Glide的缓存设计既考虑的内存缓存也考虑了硬盘缓存,内存缓存的目的是为了防止应用重复讲图片的数据读取到内存中,硬盘缓存是为了防止应用重复从网络或其他地方重复下载和读取数据。
缓存的Key使用了多个参数结合,宽高不一样也会造成可以值不同。
内存缓存:Glide默认开启内存缓存,即内存的数据没有被清除之前,不需要从硬盘或者网络上读取,提高了加载速度和用户体验,当然Glide也可以禁止使用内存缓存,使用skipMemoryCache(true):Glide.wit(this).load(uri).skipMemoryCacge(true).into(imageView)。
Glide内存缓存的实现,主要使用了LruCache算法(Least Recently Used),即最近最少使用算法,除了LRUCache算法之外,Glide还用到了弱引用机制,共同完成内存缓存功能。
硬盘缓存:Glide默认开启硬盘缓存,如果需要禁止硬盘缓存,使用diskCacheStrategy(DiskCacheStrategy.NONE)。 diskCacheStrategy提供了四种参数:
DiskCacheStrategy.NONE: 表示不缓存任何内容。
DiskCacheStrategy.SOURCE: 表示只缓存原始图片。
DiskCacheStrategy.RESULT: 表示只缓存转换过后的图片(默认选项)。
DiskCacheStrategy.ALL : 表示既缓存原始图片,也缓存转换过后的图片。
Glide默认不会将原始图片展示出来,而是会对图片进行压缩和转换。硬盘缓存的实现也是利用LruCache算法,而且Google也提供了一个工具类DiskCache,
缓存问题之缓存失效:有的url地址会在图片的url地址上添加一个token参数,做保护验证,但是token可能会变导致缓存视效,例如http://url.com/image.jpg?token=d9caa6e02c990b0a。问题原因是token变了,图片传入的url变了,缓存的key也跟着变了,导致缓存失效,解决的方法是理解缓存key的构造,重写GlideUrl的getCacheKey()方法,在此方法中将传入的url的token过滤掉,这样不管token怎样变,缓存key是不变的。
8.into方法的深入学习
Glide的into方法不止可以传递ImageView对象,也可以传递Glide的一个内部Target对象,实现target接口的对象有很多,主要使用的是SimpleTarget和ViewTarget。
SimpleTarget使用,如下继承SimpleTarget,重写onResourceReady方法,此方法中的回调传递了图片对象的实例,如果确认加载的图片不是一个GIF图片,可以指定SimpTarget的泛型为Bitmap对象。
SimpleTarget simpleTarget = new SimpleTarget() {
@Override public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) {
imageView.setImageDrawable(resource);
}
};
ViewTarget使用,Gilde默认创建的是GlideDrawableImageVIewTarget就是ViewTarget的子类,被限制只能作用于ImageView。而ViewTarget的功能更加广泛,作用于任何View。例如:自定义布局,在布局内自定义ViewTarget,在onResourceReady回调中给此布局设置背景,这样通过Glide即可以传递自定义布局的Target对象。
public classMyLayoutextendsLinearLayout{ private ViewTarget viewTarget;
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
viewTarget = new ViewTarget(this) {
@Override public void onResourceReady(GlideDrawable resource, GlideAnimation glideAnimation) {
MyLayout myLayout = getView();
myLayout.setImageAsBackground(resource);
}
};
}
public ViewTarget getTarget() {
return viewTarget;
}
public void setImageAsBackground(GlideDrawable resource) {
setBackground(resource);
}
}
调用方式:Glide.with(this).load(url).into(myLayout.getTarget());
9.preload()方法
Glide可以使用reload方法实现预加载功能,使用方式是:Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.SOURCE).preload(),即会加载原生的图片到缓存中;使用的时候:Glide.whit(this).load(uri).diskCacehStrategy(DiskCacheStrategy.SOURCE).into(imageView)。特殊说明使用Strategy.SOURCE指定缓存的对象是原生图片,因为preload默认缓存的就是原始图片,而into默认的是根据imageView大小动态调整的大小,如果不指定缓存方式,会导致into重新从网上获取图片,预加载功能失效。
preload有两个重载方法,不传递参数代码缓存原始图片大小,传递参数可以指定缓存图片的宽高。
10.downloadOnly()方法
downloadOnly只下载图片,不会对图片进行加载,下载完之后我们可以获取图片的存储路径,进行后续操作。downloadOnly有两个重载方法。
downloadOnly(int width,int height) 用于子线程下载图片,原因返回的FureTarget的对象的get方法会在子线程中等待图片下载完成才返回结果,如果下载原生图片传递Target.SIZE.ORIGINAL即可。使用方法:FutureTarget target = Glide.with(getApplicationContext()).load(url).downloadOnly(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL); File imagFile = target.get();之后我们可以采用如下方法加载这张图片。Glide.with(this).load(url).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(imageView); 注意缓存的策略必须知道加载方式为DiskCacheStrategy.SOURCE或者DiskCacheStrategy.ALL,否则Glide将无法使用刚才下载好的图片缓存文件。
downloadOnly(Y target) 用于在主线程下载图片。传递的target需要我们自己去实现,注意target的泛型必现指定为FIle类型,主要是实现两个方法,一个是getSize()方法,一个是onResourceReady()方法。getSize()中返回计算图片的大小,onResourceReady()回调方法的参数有我们需要的File对象可以供我们后续使用。使用方式Glide.with(this) .load(url).downloadOnly(new DownloadImageTarget());
11.listener()方法
Glide的监听图片加载状态,是否成功或者失败,可以使用Listener()方法监听,使用方式:Glide.with(this).load(uri)..listener(new RequestListener() {..onException()..onResourceReady().}).into(imageView)。其中onException()是加载失败的回调,onResourceReady是加载成功的回调。两个函数的返回值如果是false则不消费时间,会继续向下传递到setErrorPlaceholder()和Target的onResourceReady()方法。如果返回true则消费事件,对应的不会向下传递事件。
12.dontTransform()方法
Glide加载图片时会对图片进行变化,如果目标的ImageView是wrap_content,默认scaleType是FIT_CENTER熟悉,这样加载图片会进行变化导致加载不是我们预期的加载原图。可以通过设置dontTransform来实现。Glide.with(this).load(uri).dontTransform().into(image); 调用此方法图片的变化操作失效,如果需要变化操作可以使用override方法指定图片的宽高。
13.图片变化的基本使用
Glide图片变化使用transform方法,Glide内置了两种图片操作,我们可以直接使用:centerCrop和fitCenter,两个方法实际也是通过transform方法来实现的。其中fitCenter:Glide.with(this).load(uri).fitCenter().into(imageView) 会按照原生比例充满屏幕,centerCrop:Glide.with(this).load(uri).centerCrop().into(imageView) 会对原图中心区域进行剪裁充满屏幕的图片,也看配合override方法指定剪裁的比例。
自定义图片变化功能,其实就是基础BitmapTransformation, 然后重写tranform方法,和getId方法,其他getId要求返回唯一一个字段,以和其他图片变化做区分。BitmapTransformation只能对静态图片进行变化,如果是Gif图片,需要自己实现Transformation接口。使用方式:Glide.with(this).load(uri).transform(new BitmapTransformation({})).into(imageView)。
图片转换目前有很多的开源库,都是通用的,地址:glide-transformations的项目主页地址是 https://github.com/wasabeef/glide-transformations 。使用: compile 'jp.wasabeef:glide-transformations:2.0.2'
14.自定义模块的基本用法
自定义模块功能可以更改Glide的配置,使用方式是自定义模块类实现GlideModule接口。重写applyOptions()方法和registerCompontes()方法。用于更改Glide的配置和替换Glide的组件。前提要是Glide识别我们自定义的模块,需要在<application>标签中加入一个meta-data配置项,其中android:name指定成我们自定义的MyGlideModule的完整路径,android:value必须指定成GlideModule,这个是固定值。
Glide常见的配置:
setMemoryCache() 用于配置Glide的内存缓存策略,默认配置是LruResourceCache。
setBitmapPool() 用于配置Glide的Bitmap缓存池,默认配置是LruBitmapPool。
setDiskCache() 用于配置Glide的硬盘缓存策略,默认配置是InternalCacheDiskCacheFactory。
setDiskCacheService() 用于配置Glide读取缓存中图片的异步执行器,默认配置是FifoPriorityThreadPoolExecutor,也就是先入先出原则。
setResizeService() 用于配置Glide读取非缓存中图片的异步执行器,默认配置也是FifoPriorityThreadPoolExecutor。
setDecodeFormat() 用于配置Glide加载图片的解码模式,默认配置是RGB_565。
替换Glide组件;例如将Glide默认的HttpURLConnection改为OkHttp:1.新建一个OkHttpFetcher类,并且同样实现DataFetcher接口;2.新建一个OkHttpGlideUrlLoader类,并且实现ModelLoader接口;3.注册到Glide当中,将原来的HTTP通讯组件给替换掉glide.register(GlideUrl.class, InputStream.class, new OkHttpGlideUrlLoader.Factory());
更简单的组件替换
Glide官方给我们提供了非常简便的HTTP组件替换方式。并且除了支持OkHttp3之外,还支持OkHttp2和Volley。只需要在gradle添加配置即可:OkHttp3{ compile 'com.squareup.okhttp3:okhttp:3.9.0' compile 'com.github.bumptech.glide:okhttp3-integration:1.5.0@aar'}; OkHttp2{compile 'com.github.bumptech.glide:okhttp-integration:1.5.0@aar' compile 'com.squareup.okhttp:okhttp:2.7.5'};Volley{compile 'com.github.bumptech.glide:volley-integration:1.5.0@aar' compile 'com.mcxiaoke.volley:library:1.0.19'}。
15.带进度的Glide图片加载
地址:http://blog.csdn.net/guolin_blog/article/details/78357251
16.Glide4
使用:implementation 'com.github.bumptech.glide:glide:4.4.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0' AndroidManifest申请网络权限。
加载图片: Glide.with(this).load(url).into(imageView); 与Glide3一样
占位图、指定图片大小、缓存机制、图片转换:
RequestOptions options = new RequestOptions().placeholder(R.drawable.ic_launcher_background).error(R.drawable.error).diskCacheStrategy(DiskCacheStrategy.NONE).override(Target.SIZE_ORIGINAL).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE) .transforms(...);
Glide.with(this).load(uri).apply(options).into(imageView);与GLide3区别多了RequestOptions对象,支持多个配置调用。
指定格式:与Glide3一样,asBitmap(),asGif(),新增asFile()方法和asDrawable()方法
listener()方法:实现RequestListener监听,回调onLoadFailed方法onResourceReady方法
Submit方法 相当于Glide3的downloadOnly方法
自定义模块:自定义模块与Glide3基本一样,差别在于Glide4不需要在AndroidManifest.xml注册了。Glide4加入了@GlideModule的注解可以让Glide识别自定义模块。