Glide 支持拉取,解码和展示视频快照,图片,和GIF动画。
Glide的Api十分灵活,开发者甚至可以插入和替换成自己喜爱的任何网络栈。默认情况下,Glide使用的是一个定制化的基于HttpUrlConnection的栈,但同时也提供了与Google Volley和Square OkHttp快速集成的工具库。
虽然Glide 的主要目标是让任何形式的图片列表的滚动尽可能地变得更快、更平滑,但实际上,Glide几乎能满足你对远程图片的拉取/缩放/显示的一切需求。
Android SDK 要求
==============
最低 SDK 版本- Glide 要求最低 SDK 版本为14(Ice Cream Sandwich)或更高版本。
编译 SDK 版本- Glide 必须针对 SDK 版本27 (Oreo MR1) 或更高版本进行编译。
所需权限
====
网络加载
通过网络连接加载图像,你应该将INTERNET和ACCESS_NETWORK_STATE权限添加到你的AndroidManifest.xml:
…
…
本地存储
要从DCIM或图片等本地文件夹加载图像,你需要添加READ_EXTERNAL_STORAGE权限:
…
…
要将 Glide 的缓存存储在公共 sdcard 上,您需要使用 WRITE_EXTERNAL_STORAGE权限:
…
…
性能
==
Glide 充分考虑了Android图片加载性能的两个关键方面:
-
1.图片解码速度
-
2.解码图片带来的资源压力
为了让用户拥有良好的App使用体验,图片不仅要快速加载,而且还不能因为过多的主线程I/O或频繁的垃圾回收导致页面的闪烁和抖动现象。
Glide使用了多个步骤来确保在Android上加载图片尽可能的快速和平滑:
-
自动、智能地下采样(downsampling)和缓存(caching),以最小化存储开销和解码次数;
-
积极的资源重用,例如字节数组和Bitmap,以最小化昂贵的垃圾回收和堆碎片影响;
-
深度的生命周期集成,以确保仅优先处理活跃的Fragment和Activity的请求,并有利于应用在必要时释放资源以避免在后台时被杀掉。
Glide基本用法
=========
-
with 传入的可以是当前上下文的对象。
-
load 加载图片,图片可以是本地图片,应用资源的图片也可以是一张网络图片。
-
placeholder 占位符是在请求正在进行时,显示的图片。
-
error 当请求永久失败时,会显示设置图片。
-
into 传入要展示图片的控件。
-
transform 用来完成剪裁(切圆)或对位图应用过滤器,但它也可以用于转换GIF动画,甚至自定义的资源类型。
简单使用
====
在build.gradle中添加依赖
implementation ‘com.github.bumptech.glide:glide:4.12.0’
加载图片
Uri uri = Uri.parse(“https://profile.csdnimg.cn/C/A/6/1_g984160547”);
// String uri = “https://profile.csdnimg.cn/C/A/6/1_g984160547”;
//上面两种写法效果相同
Glide.with(this).load(uri).into(agb.ivInitial);
//应用资源
Glide.with(this).load(R.mipmap.sc1).into(agb.ivAppMipmap);
//画圆
Glide.with(this).load(uri).circleCrop().into(agb.ivCirclecrop);
//增加占位符和加载失败显示图片
Glide.with(this).load(uri).
placeholder(R.mipmap.sc1)
.error(R.mipmap.sc2)
.into(agb.ivInitial);
FutureTarget target= Glide.with(this)
.asBitmap()
.load(uri)
.submit();
new Thread(new Runnable() {
@Override
public void run() {
try {
Bitmap bitmap = target.get();//同步请求
//子线程切主线程更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
agb.ivOptions.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
取消加载
Glide.with(this).clear(agb.ivCirclecrop);
注意: 尽管及时取消不必要的加载是很好的实践,但这并不是必须的操作。实际上,当 Glide.with() 中传入的 Activity 或 Fragment 实例销毁时,Glide 会自动取消加载并回收资源。
Generated API
=============
Glide v4 使用 注解处理器 (Annotation Processor) 来生成出一个 API,它允许应用扩展 Glide 的 API并包含各种集成库提供的组件。
Generated API 模式的设计出于以下两个目的:
-
1.集成库可以为 Generated API 扩展自定义选项。
-
2.在 Application 模块中可将常用的方法组打包成一个选项在 Generated API 中使用
虽然以上所说的工作均可以通过手动创建 RequestOptions 子类的方式来完成,但想将它用好更具有挑战,并且降低了 API 使用的流畅性。
使用Generated API(高级用法)
=====================
1.在build.gradle中添加依赖
annotationProcessor ‘com.github.bumptech.glide:compiler:4.12.0’
2.创建一个添加有 @GlideModule 注解,继承自 AppGlideModule 的类。此类可生成出一个流式 API,内联了多种选项和集成库中自定义的选项:
@GlideModule
public class MyGlideModule extends AppGlideModule
{
}
3.生成的 API 默认名为 GlideApp ,与 AppGlideModule 的子类包名相同。在 Application 模块中将 Glide.with() 替换为 GlideApp.with(),即可使用该 API 去完成加载工作。
GlideApp.with(this).load(uri).circleCrop().into(agb.ivCirclecrop);
Android Studio 在大多数时候都可以正确地处理注解处理器 (annotation processor) 和 generated API。然而,当你第一次添加你的 AppGlideModule 或做了某些类型的修改后,你可能需要重新构建 (rebuild) 你的项目。 如果你发现 API 没有被 import ,你可以通过以下方法重新构建:
-
1.打开 Build 菜单;
-
2.点击 Rebuild Project。
定制请求
Glide 提供了许多可应用于单一请求的选项,包括变换、过渡、缓存选项等。
1.默认选项可以直接应用于请求上:
GlideApp.with(this).load(uri)
.placeholder(R.mipmap.sc2)
.error(R.mipmap.sc1)
.override(150)
.circleCrop().into(agb.ivOptions);
2.通过 RequestOptions 类来在多个请求之间共享:
RequestOptions requestOptions = new RequestOptions().circleCrop()
.placeholder(R.mipmap.sc2)
.error(R.mipmap.sc1).override(150);
GlideApp.with(this).load(uri).apply(requestOptions).into(agb.ivOptions);
GlideApp.with(this).load(uri).apply(requestOptions).into(agb.ivCirclecrop);
GlideExtension
Glide Generated API 可在 Application 和 Library 中被扩展。扩展使用被注解的静态方法来添加新的选项、修改现有选项、甚至添加额外的类型支持。
被 @GlideExtension 注解的类应以工具类的思维编写。这种类应该有一个私有的、空的构造方法,应为 final 类型,并且仅包含静态方法。被注解的类可以含有静态变量,可以引用其他的类或对象。
被 @GlideExtention 注解的类有两种扩展方式:
-
GlideOption - 为 RequestOptions 添加一个自定义的选项。
-
GlideType - 添加对新的资源类型的支持(GIF,SVG 等等)。
GlideOption
1.创建一个添加有 @GlideExtension注解的类。此类可生成出一个流式 API,内联了多种选项和集成库中自定义的选项:
@GlideExtension
public final class MyGlideExtension {
private MyGlideExtension(){}
@GlideOption
public static BaseRequestOptions<?> applyHeadScc(BaseRequestOptions<?> options,int size){
return options.circleCrop()
.override(size)
.placeholder(R.mipmap.sc2)
.error(R.mipmap.sc1);
}
}
2.这将在RequestOptions子类中生成一个如下所示的方法:
public class GlideOptions extends RequestOptions {
/**
* @see MyGlideExtension#applyHeadScc(BaseRequestOptions, int)
*/
@SuppressWarnings(“unchecked”)
@CheckResult
@NonNull
public GlideOptions applyHeadScc(int size) {
return (GlideOptions) MyGlideExtension.applyHeadScc(this, size);
}
…
}
3.可以根据需要在方法中包含任意数量的附加参数,只要第一个参数始终为RequestOptions:
@GlideOption
public static BaseRequestOptions<?> applyHeadScc(BaseRequestOptions<?> options,int size){
return options.circleCrop()
.override(size)
.placeholder(R.mipmap.sc2)
.error(R.mipmap.sc1);
}
4.附加参数将作为参数添加到生成的方法中:
public GlideOptions applyHeadScc(int size) {
return (GlideOptions) MyGlideExtension.applyHeadScc(this, size);
}
5.使用生成的GlideApp类调用你的自定义方法:
GlideApp.with(this)
.load(uri)
.applyHeadScc(150)
.into(agb.ivOptions);
带有GlideOption注释的方法应该是静态的并返回BaseRequestOptions< ? >。 注意: 生成的方法在标准Glide和RequestOptions类上不可用,只有Generated 的等效项可用。
高斯模糊(效果图)
1.使用库 传送门
implementation ‘jp.wasabeef:glide-transformations:4.3.0’
开始使用
@GlideOption
public static BaseRequestOptions<?> applyBlurHeadScc(BaseRequestOptions<?> options,int size){
BlurTransformation blurTransformation = new BlurTransformation(20,1);
return options
.override(size)
.placeholder(R.mipmap.sc2)
.error(R.mipmap.sc1)
// .circleCrop()
// .transform(blurTransformation);
// .transform(blurTransformation,new CircleCrop());
.transform(new MultiTransformation<>(blurTransformation,new CircleCrop()));
}
注意: 默认情况下,对每一个后续呼叫transform()或任何特定的transform方法(fitCenter(),centerCrop(),bitmapTransform()等)将取代先前的transform。
要将多个转换应用于单个加载,请使用MultiTransformation类或快捷 .transforms() 方法。
2.自定义Transformation 你也可以继承BitmapTransformation,重写transform方法,下面贴出glide-transformations里面的BlurTransformation类,一起学习一下。
public class BlurTransformation extends BitmapTransformation {
private static final int VERSION = 1;
private static final String ID =
“jp.wasabeef.glide.transformations.BlurTransformation.” + VERSION;
private static final int MAX_RADIUS = 25;
private static final int DEFAULT_DOWN_SAMPLING = 1;
private final int radius;
private final int sampling;
public BlurTransformation() {
this(MAX_RADIUS, DEFAULT_DOWN_SAMPLING);
}
public BlurTransformation(int radius) {
this(radius, DEFAULT_DOWN_SAMPLING);
}
public BlurTransformation(int radius, int sampling) {
this.radius = radius;
this.sampling = sampling;
}
@Override
protected Bitmap transform(@NonNull Context context, @NonNull BitmapPool pool,
@NonNull Bitmap toTransform, int outWidth, int outHeight) {
int width = toTransform.getWidth();
int height = toTransform.getHeight();
int scaledWidth = width / sampling;
int scaledHeight = height / sampling;
Bitmap bitmap = pool.get(scaledWidth, scaledHeight, Bitmap.Config.ARGB_8888);
setCanvasBitmapDensity(toTransform, bitmap);
Canvas canvas = new Canvas(bitmap);
canvas.scale(1 / (float) sampling, 1 / (float) sampling);
Paint paint = new Paint();
paint.setFlags(Paint.FILTER_BITMAP_FLAG);
canvas.drawBitmap(toTransform, 0, 0, paint);
try {
bitmap = RSBlur.blur(context, bitmap, radius);
} catch (RSRuntimeException e) {
bitmap = FastBlur.blur(bitmap, radius, true);
}
return bitmap;
}
@Override
public String toString() {
return “BlurTransformation(radius=” + radius + “, sampling=” + sampling + “)”;
}
@Override
public boolean equals(Object o) {
return o instanceof BlurTransformation &&
((BlurTransformation) o).radius == radius &&
((BlurTransformation) o).sampling == sampling;
}
@Override
public int hashCode() {
return ID.hashCode() + radius * 1000 + sampling * 10;
}
@Override
public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
messageDigest.update((ID + radius + sampling).getBytes(CHARSET));
}
}
GlideType
GlideType带注释的静态方法扩展RequestManager。GlideType带注释的方法允许您添加对新类型的支持,包括指定默认选项。
1.例如,要添加对 GIF 的支持(选择资源类型),你可以添加一个GlideType方法:
@GlideType(GifDrawable.class)
public static RequestBuilder scGif(RequestBuilder requestBuilder) {
return requestBuilder
.transition(new DrawableTransitionOptions())
.apply(decodeTypeOf(GifDrawable.class).lock());
}
方法名为什么叫scGif,而不是asGif,因为GlideRequests中已经有一个asGif方法。
2.将在GlideRequests生成一个如下所示的方法:
public class GlideRequests extends RequestManager {
public GlideRequest scGif() {
return (GlideRequest) MyGlideExtension.scGif(this.as(GifDrawable.class));
}
…
}
3.使用生成的GlideApp类来调用您的自定义类型(选择资源类型):
GlideApp.with(this)
.scGif()
.load(uri)
.applyBlurHeadScc(150)
.addListener(new RequestListener() {
@Override
public boolean onLoadFailed(GlideException e, Object model, Target target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GifDrawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.into(agb.ivCirclecrop);
RequestListener 返回的类型为你scGif设置的GifDrawable 相对应。
submit同步获取图片资源
FutureTarget target= GlideApp.with(this)
.asBitmap()
.load(uri)
.applyBlurHeadScc(150)
.submit();
//因target.get()是同步请求
//所以用线程转异步请求
new Thread(new Runnable() {
@Override
public void run() {
try {
Bitmap bitmap = target.get();//同步请求
//子线程切主线程更新UI
runOnUiThread(new Runnable() {
@Override
public void run() {
agb.ivOptions.setImageBitmap(bitmap);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
效果跟之前的一样一样的。 这个功能就是有特殊需求时对获取的图片进行特殊处理。
Application Options(选项)
=======================
Glide 允许应用通过 AppGlideModule 实现来完全控制 Glide 的内存和磁盘缓存使用。Glide 试图提供对大部分应用程序合理的默认选项,但对于部分应用,可能就需要定制这些值。在你做任何改变时,请注意测量其结果,避免出现性能的倒退。
Memory cache(内存缓存)
默认情况下,Glide使用 LruResourceCache ,这是 MemoryCache 接口的一个缺省实现,使用固定大小的内存和 LRU 算法。LruResourceCache 的大小由 Glide 的 MemorySizeCalculator 类来决定,这个类主要关注设备的内存类型,设备 RAM 大小,以及屏幕分辨率。
1.自定义 MemoryCache 的大小,具体是在它们的 AppGlideModule 中使用 applyOptions(Context, GlideBuilder) 方法配置 MemorySizeCalculator:
@GlideModule
public class MyGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
ndroid移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-UHrxxZq9-1712504854968)]
[外链图片转存中…(img-EMeVIpNJ-1712504854969)]
[外链图片转存中…(img-MQxB4493-1712504854969)]
[外链图片转存中…(img-ANzlYogU-1712504854970)]
[外链图片转存中…(img-T3HeXHaP-1712504854970)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2020-2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图、Android开发面试专题资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中…(img-WhGSbsKD-1712504854970)]
[外链图片转存中…(img-7ihxOR7D-1712504854971)]
[外链图片转存中…(img-vlzmsocJ-1712504854971)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!