github
使用方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31String url="https://upload-images.jianshu.io/upload_images/5363507-476c8bb17b124d22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240";
// //圆形图片
ImageLoaderV4.getInstance().displayCircleImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_1, R.mipmap.ic_launcher_round);
//圆角图片
ImageLoaderV4.getInstance().displayRoundImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_2, R.mipmap.ic_launcher_round, 40);
//模糊图片
ImageLoaderV4.getInstance().displayBlurImage(this, "http://imgsrc.baidu.com/imgad/pic/item/267f9e2f07082838b5168c32b299a9014c08f1f9.jpg", mImageView_3, R.mipmap.ic_launcher_round, 10);
//本地图片 不做处理
ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_4);
// TODO: 2018/4/20 以下的三种不介意使用,需要解决一些问题 start
//本地图片,模糊处理
ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_5, new BlurBitmapTranformation( 200));
//本地图片,裁圆角处理
ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_6, new GlideCircleTransformation());
//四周倒角处理
ImageLoaderV4.getInstance().displayImageInResource(this, R.mipmap.test, mImageView_7, new RoundBitmapTranformation( 40));
// TODO: 2018/4/20 以上的三种不介意使用,需要解决一些问题 start
//使用的是另外一种方法,指定传入的那种的方法 ,还可以不断的扩展,不断的扩展,这是Gilded提供的一些操作,牛逼 ,牛逼 这是对本地图片的操作
ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_8, new CenterInside(), R.mipmap.test);
ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_9, new CircleCrop(), R.mipmap.test);
ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_10, new FitCenter(), R.mipmap.test);
ImageLoaderV4.getInstance().displayImageInResourceTransform(this, R.mipmap.test, mImageView_11, new RoundedCorners(10), R.mipmap.test);
//对网络图片的操作
ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_12, R.mipmap.test,new CenterInside());
ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_13, R.mipmap.test,new CircleCrop());
ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_14, R.mipmap.test,new FitCenter());
ImageLoaderV4.getInstance().displayImageByNet(this,url,mImageView_15, R.mipmap.test,new RoundedCorners(10));
实现效果:监听图片的下载进度,注意事项需要在监听返回键的时候,取消请求1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26ImageLoaderV4.getInstance().disPlayImageProgress(this, "http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png", mImageView_8, R.mipmap.test, R.mipmap.test, new OnGlideImageViewListener() {
@Override
public void onProgress(int percent, boolean isDone, GlideException exception) {
System.out.println("shiming percent="+percent);
System.out.println("shiming isDone="+isDone);
mProgress.setText("我在主线程,进度是多少=="+percent+"%");
if (isDone){
mProgress.setText("我在主线程,进度是多少==100%");
}
}
});
ImageLoaderV4.getInstance().disPlayImageProgressByOnProgressListener(this, "http://img.zcool.cn/community/0142135541fe180000019ae9b8cf86.jpg@1280w_1l_2o_100sh.png", mImageView_7, R.mipmap.test, R.mipmap.test, new OnProgressListener() {
@Override
public void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception) {
System.out.println("shiming bytesRead="+bytesRead);
System.out.println("shiming totalBytes="+totalBytes);
mProgress7.setText("我在主线程,进度是多少==+bytesRead"+bytesRead+"totalBytes="+totalBytes);
if (isDone){
mProgress7.setText("我在主线程,进度是多少==100%");
}
}
});
使用内部提供的图片处理
加入依赖1
2
3compile 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
compile "com.github.bumptech.glide:okhttp3-integration:4.5.0"
构建AppGlideModule
初始化registerComponents()方法,使用okhttp加入拦截器1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16/**
OkHttp 是一个底层网络库(相较于 Cronet 或 Volley 而言),尽管它也包含了 SPDY 的支持。
OkHttp 与 Glide 一起使用可以提供可靠的性能,并且在加载图片时通常比 Volley 产生的垃圾要少。
对于那些想要使用比 Android 提供的 HttpUrlConnection 更 nice 的 API,
或者想确保网络层代码不依赖于 app 安装的设备上 Android OS 版本的应用,OkHttp 是一个合理的选择。
如果你已经在 app 中某个地方使用了 OkHttp ,这也是选择继续为 Glide 使用 OkHttp 的一个很好的理由,就像选择其他网络库一样。
添加 OkHttp 集成库的 Gradle 依赖将使 Glide 自动开始使用 OkHttp 来加载所有来自 http 和 https URL 的图片
* @param context
* @param glide
* @param registry
*/
@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
super.registerComponents(context, glide, registry);
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
}
默认情况下,Glide使用 LruResourceCache , 这是 MemoryCache 接口的一个缺省实现,使用固定大小的内存和 LRU 算法。 LruResourceCache 的大小由 Glide 的 MemorySizeCalculator 类来决定,这个类主要关注设备的内存类型,设备 RAM 大小,以及屏幕分辨率。应用程序可以自定义 MemoryCache 的大小, 具体是在它们的 AppGlideModule 中使用applyOptions(Context, GlideBuilder) 方法配置 MemorySizeCalculator1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 //Glide会自动合理分配内存缓存,但是也可以自己手动分配。
// @Override
// public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
// super.applyOptions(context, builder);
// //1、setMemoryCacheScreens设置MemoryCache应该能够容纳的像素值的设备屏幕数,
// // 说白了就是缓存多少屏图片,默认值是2。
// //todo 建议不要设置,使用glide 默认
//// MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)
//// .setMemoryCacheScreens(2)
//// .build();
//// builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));
//
// //2。也可以直接覆写缓存大小:todo 建议不要设置,使用glide 默认
//// int memoryCacheSizeBytes = 1024 * 1024 * 20; // 20mb
//// builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));
//// 3.甚至可以提供自己的 MemoryCache 实现:
//// builder.setMemoryCache(new YourAppMemoryCacheImpl());
// }
Bitmap 池Glide 使用 LruBitmapPool 作为默认的 BitmapPool LruBitmapPool 是一个内存中的固定大小的 BitmapPool,使用 LRU 算法清理。默认大小基于设备的分辨率和密度,同时也考虑内存类和 isLowRamDevice 的返回值。 具体的计算通过 Glide 的 MemorySizeCalculator 来完成,与 Glide 的 MemoryCache 的大小检测方法相似。
1 | // @Override |
磁盘缓存Glide 使用 DiskLruCacheWrapper 作为默认的 磁盘缓存 . DiskLruCacheWrapper 是一个使用 LRU 算法的固定大小的磁盘缓存。默认磁盘大小为 250 MB , 位置是在应用的 缓存文件夹 中的一个 特定目录 。
1 | @Override |
1 | /** |
为了维持对 Glide v3 的 GlideModules 的向后兼容性, Glide 仍然会解析应用程序和所有被包含的库中的 AndroidManifest.xml 文件, 并包含在这些清单中列出的旧 GlideModules 模块类。如果你已经迁移到 Glide v4 的 AppGlideModule 和 LibraryGlideModule ,你可以完全禁用清单解析。 这样可以改善 Glide 的初始启动时间,并避免尝试解析元数据时的一些潜在问题。要禁用清单解析, 请在你的 AppGlideModule 实现中复写 isManifestParsingEnabled() 方法:
1 | @Override |
IImageLoaderClient接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/**
* Created by shiming on 2016/10/26.
*/
public interface IImageLoaderClient {
public void init(Context context);
public void destroy(Context context);
public File getCacheDir(Context context);
public void clearMemoryCache(Context context);
public void clearDiskCache(Context context);
public Bitmap getBitmapFromCache(Context context, String url);
public void getBitmapFromCache(Context context, String url, IGetBitmapListener listener);
public void displayImage(Context context, int resId, ImageView imageView);
public void displayImage(Context context, String url, ImageView imageView);
public void displayImage(Context context, String url, ImageView imageView, boolean isCache);
public void displayImage(Fragment fragment, String url, ImageView imageView);
public void displayImage(Context context, String url, ImageView imageView, int defRes);
public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes);
public void displayImage(Context context, String url, ImageView imageView, int defRes, BitmapTransformation transformations);
public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, BitmapTransformation transformations);
public void displayImage(Context context, String url, ImageView imageView, int defRes, ImageSize size);
public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, ImageSize size);
public void displayImage(Context context, String url, ImageView imageView, int defRes, boolean cacheInMemory);
public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, boolean cacheInMemory);
public void displayImage(Context context, String url, ImageView imageView, IImageLoaderListener listener);
public void displayImage(Fragment fragment, String url, ImageView imageView, IImageLoaderListener listener);
public void displayImage(Context context, String url, ImageView imageView, int defRes, IImageLoaderListener listener);
public void displayImage(Fragment fragment, String url, ImageView imageView, int defRes, IImageLoaderListener listener);
public void displayCircleImage(Context context, String url, ImageView imageView, int defRes);
public void displayCircleImage(Fragment fragment, String url, ImageView imageView, int defRes);
public void displayRoundImage(Context context, String url, ImageView imageView, int defRes, int radius);
public void displayRoundImage(Fragment fragment, String url, ImageView imageView, int defRes, int radius);
public void displayBlurImage(Context context, String url, int blurRadius, IGetDrawableListener listener);
public void displayBlurImage(Context context, String url, ImageView imageView, int defRes, int blurRadius);
public void displayBlurImage(Context context, int resId, ImageView imageView, int blurRadius);
public void displayBlurImage(Fragment fragment, String url, ImageView imageView, int defRes, int blurRadius);
public void displayImageInResource(Context context, int resId, ImageView imageView);
public void displayImageInResource(Fragment fragment, int resId, ImageView imageView);
public void displayImageInResource(Context context, int resId, ImageView imageView, BitmapTransformation transformations);
public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, BitmapTransformation transformations);
public void displayImageInResource(Context context, int resId, ImageView imageView, int defRes);
public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, int defRes);
public void displayImageInResource(Context context, int resId, ImageView imageView, int defRes, BitmapTransformation transformations);
public void displayImageInResource(Fragment fragment, int resId, ImageView imageView, int defRes, BitmapTransformation transformations);
//add shiming 2018.4.20 transformation 需要装换的那种图像的风格,错误图片,或者是,正在加载中的错误图
public void displayImageInResourceTransform(Activity activity, int resId, ImageView imageView, Transformation transformation, int errorResId);
public void displayImageInResourceTransform(Context context, int resId, ImageView imageView, Transformation transformation, int errorResId);
public void displayImageInResourceTransform(Fragment fragment, int resId, ImageView imageView, Transformation transformation, int errorResId);
//这是对网络图片,进行的图片操作,使用的glide中的方法
public void displayImageByNet(Context context, String url, ImageView imageView, int defRes,Transformation transformation);
public void displayImageByNet(Fragment fragment, String url, ImageView imageView, int defRes,Transformation transformation);
public void displayImageByNet(Activity activity, String url, ImageView imageView, int defRes,Transformation transformation);
/**
* 停止图片的加载,对某一个的Activity
* @hide
*/
public void clear(Activity activity,ImageView imageView);
/**
* 停止图片的加载,context
* {@hide}
*/
public void clear(Context context,ImageView imageView);
/**
* 停止图片的加载,fragment
* {@hide}
*/
public void clear(Fragment fragment,ImageView imageView);
//如果需要的话,需要指定加载中,或者是失败的图片
public void displayImageByDiskCacheStrategy(Fragment fragment, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
public void displayImageByDiskCacheStrategy(Activity activity, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
public void displayImageByDiskCacheStrategy(Context context, String url, DiskCacheStrategy diskCacheStrategy,ImageView imageView);
//某些情形下,你可能希望只要图片不在缓存中则加载直接失败(比如省流量模式)
public void disPlayImageOnlyRetrieveFromCache(Fragment fragment,String url,ImageView imageView);
public void disPlayImageOnlyRetrieveFromCache(Activity activity,String url,ImageView imageView);
public void disPlayImageOnlyRetrieveFromCache(Context context,String url,ImageView imageView);
/**
*如果你想确保一个特定的请求跳过磁盘和/或内存缓存(比如,图片验证码 –)
* @param fragment
* @param url
* @param imageView
* @param skipflag 是否跳过内存缓存
* @param diskCacheStratey 是否跳过磁盘缓存
*/
public void disPlayImageSkipMemoryCache(Fragment fragment,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);
public void disPlayImageSkipMemoryCache(Activity activity,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);
public void disPlayImageSkipMemoryCache(Context context,String url,ImageView imageView,boolean skipflag,boolean diskCacheStratey);
/**
* 知道这个图片会加载失败,那么的话,我们可以重新加载
* @param fragment
* @param url
* @param fallbackUrl
* @param imageView
*/
//从 Glide 4.3.0 开始,你可以很轻松地使用 .error() 方法。这个方法接受一个任意的 RequestBuilder,它会且只会在主请求失败时开始一个新的请求:
public void disPlayImageErrorReload(Fragment fragment,String url,String fallbackUrl,ImageView imageView);
public void disPlayImageErrorReload(Activity activity,String url,String fallbackUrl,ImageView imageView);
public void disPlayImageErrorReload(Context context,String url,String fallbackUrl,ImageView imageView);
/**
未来 Glide 将默认加载硬件位图而不需要额外的启用配置,只保留禁用的选项 现在已经默认开启了这个配置,但是在有些情况下需要关闭
所以提供了以下的方法,禁用硬件位图 disallowHardwareConfig
* @param fragment
* @param url
* @param imageView
*/
// 哪些情况不能使用硬件位图?
// 在显存中存储像素数据意味着这些数据不容易访问到,在某些情况下可能会发生异常。已知的情形列举如下:
// 在 Java 中读写像素数据,包括:
// Bitmap#getPixel
// Bitmap#getPixels
// Bitmap#copyPixelsToBuffer
// Bitmap#copyPixelsFromBuffer
// 在本地 (native) 代码中读写像素数据
// 使用软件画布 (software Canvas) 渲染硬件位图:
// Canvas canvas = new Canvas(normalBitmap)
//canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
// 在绘制位图的 View 上使用软件层 (software layer type) (例如,绘制阴影)
// ImageView imageView = …
// imageView.setImageBitmap(hardwareBitmap);
//imageView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
// 打开过多的文件描述符 . 每个硬件位图会消耗一个文件描述符。
// 这里存在一个每个进程的文件描述符限制 ( Android O 及更早版本一般为 1024,在某些 O-MR1 和更高的构建上是 32K)。
// Glide 将尝试限制分配的硬件位图以保持在这个限制以内,但如果你已经分配了大量的文件描述符,这可能是一个问题。
// 需要ARGB_8888 Bitmaps 作为前置条件
// 在代码中触发截屏操作,它会尝试使用 Canvas 来绘制视图层级。
// 作为一个替代方案,在 Android O 以上版本你可以使用 PixelCopy.
// 共享元素过渡 (shared element transition)(OMR1已修复)
public void disPlayImagedisallowHardwareConfig(Fragment fragment,String url,ImageView imageView);
public void disPlayImagedisallowHardwareConfig(Activity activity,String url,ImageView imageView);
public void disPlayImagedisallowHardwareConfig(Context context,String url,ImageView imageView);
//监听图片的下载进度,是否完成,百分比 也可以加载本地图片,扩张一下
public void disPlayImageProgress(Context context,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);
public void disPlayImageProgress(Activity activity,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);
public void disPlayImageProgress(Fragment fragment,String url,ImageView imageView,int placeholderResId,int errorResId,OnGlideImageViewListener listener);
public void disPlayImageProgressByOnProgressListener(Context context,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);
public void disPlayImageProgressByOnProgressListener(Activity activity,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);
public void disPlayImageProgressByOnProgressListener(Fragment fragment,String url,ImageView imageView,int placeholderResId,int errorResId, OnProgressListener onProgressListener);
// TransitionOptions 用于给一个特定的请求指定过渡。
// 每个请求可以使用 RequestBuilder 中的 transition()
// 方法来设定 TransitionOptions 。还可以通过使用
// BitmapTransitionOptions 或 DrawableTransitionOptions
// 来指定类型特定的过渡动画。对于 Bitmap 和 Drawable
// 之外的资源类型,可以使用 GenericTransitionOptions。 Glide v4 将不会默认应用交叉淡入或任何其他的过渡效果。每个请求必须手动应用过渡。
public void displayImageByTransition(Context context, String url, TransitionOptions transitionOptions, ImageView imageView);
public void displayImageByTransition(Activity activity, String url, TransitionOptions transitionOptions, ImageView imageView);
public void displayImageByTransition(Fragment fragment, String url, TransitionOptions transitionOptions, ImageView imageView);
//失去焦点,建议实际的项目中少用,取消求情
public void glidePauseRequests(Context context);
public void glidePauseRequests(Activity activity);
public void glidePauseRequests(Fragment fragment);
//获取焦点,建议实际的项目中少用
public void glideResumeRequests(Context context);
public void glideResumeRequests(Activity activity);
public void glideResumeRequests(Fragment fragment);
//加载缩图图 int thumbnailSize = 10;//越小,图片越小,低网络的情况,图片越小
//GlideApp.with(this).load(urlnoData).override(thumbnailSize))// API 来强制 Glide 在缩略图请求中加载一个低分辨率图像
public void displayImageThumbnail(Context context,String url,String backUrl,int thumbnailSize,ImageView imageView);
public void displayImageThumbnail(Activity activity,String url,String backUrl,int thumbnailSize,ImageView imageView);
public void displayImageThumbnail(Fragment fragment,String url,String backUrl,int thumbnailSize,ImageView imageView);
//如果没有两个url的话,也想,记载一个缩略图
public void displayImageThumbnail(Fragment fragment,String url,float thumbnailSize,ImageView imageView);
public void displayImageThumbnail(Activity activity,String url,float thumbnailSize,ImageView imageView);
public void displayImageThumbnail(Context context,String url,float thumbnailSize,ImageView imageView);
}
GlideImageLoaderClient实现类
1 | package code.shiming.com.imageloader471; |
ImageLoaderV4调用类
1 | package code.shiming.com.imageloader471; |
关于图片下载进度的监听,在AppGlideModuleProgress 需要初始化ProgressManager1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19@GlideModule
public class AppGlideModuleProgress extends AppGlideModule {
/**
OkHttp 是一个底层网络库(相较于 Cronet 或 Volley 而言),尽管它也包含了 SPDY 的支持。
OkHttp 与 Glide 一起使用可以提供可靠的性能,并且在加载图片时通常比 Volley 产生的垃圾要少。
对于那些想要使用比 Android 提供的 HttpUrlConnection 更 nice 的 API,
或者想确保网络层代码不依赖于 app 安装的设备上 Android OS 版本的应用,OkHttp 是一个合理的选择。
如果你已经在 app 中某个地方使用了 OkHttp ,这也是选择继续为 Glide 使用 OkHttp 的一个很好的理由,就像选择其他网络库一样。
添加 OkHttp 集成库的 Gradle 依赖将使 Glide 自动开始使用 OkHttp 来加载所有来自 http 和 https URL 的图片
* @param context
* @param glide
* @param registry
*/
@Override
public void registerComponents(Context context, Glide glide, Registry registry) {
super.registerComponents(context, glide, registry);
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(ProgressManager.getOkHttpClient()));
}
}
ProgressManager
1 | public class ProgressManager { |
ProgressResponseBody1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48public class ProgressResponseBody extends ResponseBody {
private String imageUrl;
private ResponseBody responseBody;
private OnProgressListener progressListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(String url, ResponseBody responseBody, OnProgressListener progressListener) {
this.imageUrl = url;
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@Override
public BufferedSource source() {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0;
@Override
public long read(@NonNull Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
totalBytesRead += (bytesRead == -1) ? 0 : bytesRead;
if (progressListener != null) {
progressListener.onProgress(imageUrl, totalBytesRead, contentLength(), (bytesRead == -1), null);
}
return bytesRead;
}
};
}
}
OnProgressListener1
2
3
4
5
6
7
8
9
10
11public interface OnProgressListener {
/**
*
* @param imageUrl 图片地址
* @param bytesRead 下载了多少字节
* @param totalBytes 总共的大小
* @param isDone 是否完成
* @param exception 异常
*/
void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception);
}
OnGlideImageViewListener1
2
3
4
5
6
7
8
9public interface OnGlideImageViewListener {
/**
*
* @param percent 下载进度的百分比,不关心,大小
* @param isDone 是否完成
* @param exception 异常
*/
void onProgress(int percent, boolean isDone, GlideException exception);
}
glide4.X优点
1、新的文档,用户可以通过提交请求到Glide’s gh-pages分支贡献。
2、用户可以添加新类型或自定义选项集来轻松地自定义Glide流畅的API。大量简化个人请求类型,确保选项始终如一,易于使用,即使您正在加载不同类型的资源。
3、各种性能改进,包括在下载采样图像时大量减少垃圾,更加智能的默认磁盘缓存策略,以及加载GIF时性能提升。
4、改进了视图大小和布局的处理,特别是在RecyclerView中。
官方文档:https://muyangmin.github.io/glide-docs-cn/
Glide V4变化较大的是库处理选项的方式。在Glide v3中,选项是由一系列复杂的多类型构建器单独处理的。在Glide v4中,这些已被具有单一类型的单个构建器和可以提供给构建器的一系列选项的对象所替代。Glide 生成的API通过将选项对象和任何包含的集成库与构建器的选项合并,来创建单个流畅的API。 可以简单理解为,Glide v4 将Glide V3中Glide.with()实现的一系列复杂功能拆分成一些独立的API。
建议看官方文档,虽然需要点时间!
#####最后总结下Glide4.X对比Glide3.X的区别:
######1、选项(Options)
Glide v4 中的一个比较大的改动是Glide库处理选项(centerCrop()
, placeholder()
等)的方式。在 v3 版本中,选项由一系列复杂的异构建造者(multityped builders)单独处理。在新版本中,由一个单一类型的唯一一个建造者接管一系列选项对象。Glide 的generated API进一步简化了这个操作:它会合并传入建造者的选项对象和任何已包含的集成库里的选项,以生成一个流畅的 API。
######2、RequestBuilder
对于这类方法:
1 | listener() |
在 Glide v4 版本中,只存在一个 RequestBuilder
对应一个你正在试图加载的类型(Bitmap
, Drawable
, GifDrawable
等)。 RequestBuilder
可以直接访问对这个加载过程有影响的选项,包括你想加载的数据模型(url, uri等),可能存在的缩略图
请求,以及任何的监听器
。RequestBuilder
也是你使用 into()
或者 preload()
方法开始加载的地方:1
2
3
4
5
6
7
8
9RequestBuilder<Drawable> requestBuilder = Glide.with(fragment)
.load(url);
requestBuilder
.thumbnail(Glide.with(fragment)
.load(thumbnailUrl))
.listener(requestListener)
.load(url)
.into(imageView);
######3、请求选项
对于这类方法:
1 | centerCrop() |
大部分选项被移动到了一个单独的称为 RequestOptions
的对象中,
1 | RequestOptions options = new RequestOptions() |
RequestOptions
允许你一次指定一系列的选项,然后对多个加载重用它们:
1 | RequestOptions myOptions = new RequestOptions() |
######4、变换
Glide v4 里的 Transformations
现在会替换之前设置的任何变换。在 Glide v4 中,如果你想应用超过一个的 Transformation
,你需要使用 transforms()
方法:
1 | Glide.with(fragment) |
或使用 generated API:
1 | GlideApp.with(fragment) |
######5、解码格式
在 Glide v3, 默认的 DecodeFormat
是 DecodeFormat.PREFER_RGB_565
,它将使用 [Bitmap.Config.RGB_565
],除非图片包含或可能包含透明像素。对于给定的图片尺寸,RGB_565
只使用 [Bitmap.Config.ARGB_8888
] 一半的内存,但对于特定的图片有明显的画质问题,包括条纹(banding)和着色(tinting)。为了避免RGB_565
的画质问题,Glide 现在默认使用 ARGB_8888
。结果是,图片质量变高了,但内存使用也增加了。
要将 Glide v4 默认的 DecodeFormat
改回 DecodeFormat.PREFER_RGB_565
,请在 AppGlideModule
中应用一个 RequestOption
:
1 | @GlideModule |
关于使用 AppGlideModules
的更多信息,请查阅 配置 页面。请注意,为了让 Glide 发现你的 AppGlideModule
实现,你必须确保添加了对 Glide 的注解解析器的依赖。关于如何设置这个库的更多信息,请查看 下载和设置。
######6、过渡选项
对于这类方法:
1 | crossFade() |
控制从占位符到图片和/或缩略图到全图的交叉淡入和其他类型变换的选项,被移动到了 TransitionOptions
中。
要应用过渡(之前的动画),请使用下列选项中符合你请求的资源类型的一个:
如果你想移除任何默认的过渡,可以使用 TransitionOptions.dontTransition()
]17 。
过渡动画通过 RequestBuilder
应用到请求上:
1 | Glide.with(fragment) |
######7、交叉淡入 (Cross fade)
不同于 Glide v3,Glide v4 将不会默认应用交叉淡入或任何其他的过渡效果。每个请求必须手动应用过渡。
要为一个特定的加载应用一个交叉淡入变换效果,你可以使用:1
2
3
4
5
6import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
Glide.with(fragment)
.load(url)
.transition(withCrossFade())
.into(imageView);
或:1
2
3
4
5
6Glide.with(fragment)
.load(url)
.transition(
new DrawableTransitionOptions
.crossFade())
.into(imageView);
######8、Generated API
为了让使用 Glide v4 更简单轻松,Glide 现在也提供了一套可以为应用定制化生成的 API。应用可以通过包含一个标记了 [AppGlideModule
][2 的实现来访问生成的 API。如果你不了解这是怎么工作的,可以查看 Generated API 。
Generated API添加了一个 GlideApp
类,该类提供了对 RequestBuilder
和 RequestOptions
子类的访问。RequestOptions
的子类包含了所有 RequestOptions
中的方法,以及 GlideExtensions
中定义的方法。RequestBuilder
的子类则提供了生成的 RequestOptions
中所有方法的访问,而不需要你再手动调用 apply
。举个例子:
在没有使用 Generated API 时,请求大概长这样:
1 | Glide.with(fragment) |
使用 Generated API,RequestOptions
的调用可以被内联:
1 | GlideApp.with(fragment) |
你仍然可以使用生成的 RequestOptions
子类来应用相同的选项到多次加载中;但生成的 RequestBuilder
子类可能在多数情况下更为方便。
######9、类型(Type)与目标(Target)
选择资源类型
Glide 允许你指定你想加载的资源类型。如果你指定了一个超类型,Glide 会尝试加载任何可用的子类型。比如,如果你请求的是 Drawable ,Glide 可能会加载一个 BitmapDrawable 或一个 GifDrawable 。而如果你请求的是一个 GifDrawable ,要么会加载出一个 GifDrawable,要么报错–只要图片不是 GIF 的话(即使它凑巧是一个完全有效的图片也是如此)。
默认请求的类型是 Drawable:
1 | Glide.with(fragment).load(url) |
如果要明确指定请求 Bitmap:
1 | Glide.with(fragment).asBitmap() |
如果要创建一个文件路径(本地图片的最佳选项):
1 | Glide.with(fragment).asFile() |
如果要下载一个远程文件到缓存然后创建文件路径:
1 | Glide.with(fragment).downloadOnly() |
######10、Drawables
Glide v3 版本中的 GlideDrawable
类已经被移除,支持标准的Android Drawable
。 GlideBitmapDrawable
也已经被删除,由 BitmapDrawable
代替之。
如果你想知道某个 Drawable 是否是动画(animated),可以检查它是否为 Animatable
的实例。
1 | boolean isAnimated = drawable instanceof Animatable; |
######11、TargetsonResourceReady
方法的签名做了一些修改。例如,对于 Drawables
:
1 | onResourceReady(GlideDrawable drawable, GlideAnimation<? super GlideDrawable> anim) |
现在改为:
1 | onResourceReady(Drawable drawable, Transition<? super Drawable> transition); |
类似地, onLoadFailed
的签名也有一些变动:
1 | onLoadFailed(Exception e, Drawable errorDrawable) |
改为:
1 | onLoadFailed(Drawable errorDrawable) |
如果你想要获得更多导致加载失败的错误信息,你可以使用 RequestListener
。
######12、取消请求Glide.clear(Target)
方法被移动到了 RequestManager
中:
1 | Glide.with(fragment).clear(target) |
使用 RequestManager
清除之前由它启动的加载过程,通常能提高性能,虽然这并不是强制要求的。Glide v4 会为每一个 Activity 和 Fragment 跟踪请求,所以你需要在合适的层级去清除请求。
######13、配置
在 Glide v3 中,配置使用一个或多个 GlideModule
来完成。而在 Glide v4 中,配置改为使用一个类似但稍微复杂的系统来完成。
关于这个新系统的细节,可以查看配置页面。
######14、应用程序
在早期版本中使用了一个 GlideModule
的应用,可以将它转换为一个 AppGlideModule
。
在 Glide v3 中,你可能会有一个像这样的 GlideModule
:
1 | public class GiphyGlideModule implements GlideModule { |
在 Glide v4 中,你需要将其转换成一个 AppGlideModule
,它看起来像这样:
1 | @GlideModule |
请注意,@GlideModule
注解不能省略。
如果你的应用拥有多个 GlideModule
,你需要把其中一个转换成 AppGlideModule
,剩下的转换成 LibraryGlideModule
。除非存在AppGlideModule
,否则程序不会发现 LibraryGlideModule
,因此您不能仅使用 LibraryGlideModule
。
######15、程序库
拥有一个或多个 GlideModule
的程序库应该使用 LibraryGlideModule
。程序库不应该使用 AppGlideModule
,因为它在一个应用里只能有一个。因此,如果你试图在程序库里使用它,将不仅会妨碍这个库的用户设置自己的选项,还会在多个程序库都这么做时造成冲突。
例如,v3 版本中 Volley 集成库的 GlideModule
:
1 | public class VolleyGlideModule implements GlideModule { |
在 v4 版本中可以转换成为一个 LibraryGlideModule
:
1 | @GlideModule |
######16、清单解析
为了简化迁移过程,尽管清单解析和旧的 GlideModule
接口已被废弃,但它们在 v4 版本中仍被支持。AppGlideModule
,LibraryGlideModule
,与已废弃的 GlideModule
可以在一个应用中共存。
然而,为了避免检查元数据的性能天花板(以及相关的 bugs ),你可以在迁移完成后禁用掉清单解析,在你的 AppGlideModule
中复写一个方法:
1 | @GlideModule |
######17、using(), ModelLoader, StreamModelLoader.
ModelLoader
ModelLoader
API 在 v4 版本中仍然存在,并且它的设计目标仍然和它在 v3 中一样,但有一些细节变化。
第一个细节,ModelLoader
的子类型如 StreamModelLoader
,现在已没有存在的必要,用户可以直接实现 ModelLoader
。例如,一个StreamModelLoader<File>
类现在可以通过 ModelLoader<File, InputStream>
的方式来实现和引用。
第二, ModelLoader
现在并不直接返回 DataFetcher
,而是返回 LoadData
。[LoadData
] 是一个非常简单的封装,包含一个磁盘缓存键和一个 DataFetcher
。
第三, ModelLoaders
有一个 handles()
方法,这使你可以为同一个类型参数注册超过一个的 ModelLoader 。
将一个 ModelLoader
从 v3 API转换到 v4 API ,通常是很简单直接的。如果你在你的 v3 ModelLoader
中只是简单滴返回一个 DataFetcher
:
1 | public final class MyModelLoader implements StreamModelLoader<File> { |
那么你在 v4 替代类上需要做的仅仅只是封装一下这个 data fetcher :
1 | public final class MyModelLoader implements ModelLoader<File, InputStream> { |
请注意,除了 DataFetcher
之外,模型也被传递给 LoadData
作为缓存键的一部分。这个规则为某些特殊场景提供了更多对磁盘缓存键的控制。大部分实现可以直接将 model 传入 LoadData
,就像上面这样。
如果你仅仅是想为某些 model(而不是所有)使用你的 ModelLoader,你可以在你尝试加载 model 之前使用 handles()
方法来检查它。如果你从 handles
方法中返回了 false
,那么你的 ModelLoader
将不能加载指定的 model ,即使你的 ModelLoader
类型 (在这个例子里是 File
和 InputStream
) 与之匹配。
举个例子,如果你在某个指定文件夹下写入了加密的图片,你可以使用 handles
方法来实现一个 ModelLoader
以从那个特定的文件夹下解密图片,但是并不用于加载其他文件夹下的 File
:
1 | public final class MyModelLoader implements ModelLoader<File, InputStream> { |
using()
using
API在 Glide v4 中被删除了,这是为了鼓励用户使用 AppGlideModule
一次性地 注册 所有组件,避免对象重用(re-use, 原文如此 –译者注)。你无需每次加载图片时都创建一个新的 ModelLoader
;你应该在 AppGlideModule
中注册一次,然后交给 Glide 在每次加载时检查 model (即你传入 load()
方法的对象)来决定什么时候使用你注册的 ModelLoader` 。
为了确保你仅为特定的 model 使用你的 ModelLoader
,请像上面展示的那样实现 handles
方法:检查每个 model ,但仅在应当使用你的 ModelLoader
时才返回 true 。
##以上17点就是Glide4.X和Glide3.X的区别,还是建议看官方文档