2024年Android最全Android Glide 的简单使用(一),2024年最新大厂面试会问什么问题

总结

现在新技术层出不穷,如果每次出新的技术,我们都深入的研究的话,很容易分散精力。新的技术可能很久之后我们才会在工作中用得上,当学的新技术无法学以致用,很容易被我们遗忘,到最后真的需要使用的时候,又要从头来过(虽然上手会更快)。

我觉得身为技术人,针对新技术应该是持拥抱态度的,入了这一行你就应该知道这是一个活到老学到老的行业,所以面对新技术,不要抵触,拥抱变化就好了。

Flutter 明显是一种全新的技术,而对于这个新技术在发布之初,花一个月的时间学习它,成本确实过高。但是周末花一天时间体验一下它的开发流程,了解一下它的优缺点、能干什么或者不能干什么。这个时间,并不是我们不能接受的。

如果有时间,其实通读一遍 Flutter 的文档,是最全面的一次对 Flutter 的了解过程。但是如果我们只有 8 小时的时间,我希望能关注一些最值得关注的点。

(跨平台开发(Flutter)、java基础与原理,自定义view、NDK、架构设计、性能优化、完整商业项目开发等)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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) {

MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)

.setMemoryCacheScreens(2)

.build();

builder.setMemoryCache(new LruResourceCache(calculator.getMemoryCacheSize()));

}

}

2.直接覆盖缓存大小:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

int memoryCacheSizeBytes = 1024 * 1024 * 10; // 10mb

builder.setMemoryCache(new LruResourceCache(memoryCacheSizeBytes));

}

}

3.提供自己的 MemoryCache 实现:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

builder.setMemoryCache(new MyMemoryCacheImpl());

}

}

Disk Cache(磁盘缓存)


Glide 使用 DiskLruCacheWrapper 作为默认的磁盘缓存。 DiskLruCacheWrapper 是一个使用 LRU 算法的固定大小的磁盘缓存。默认磁盘大小为 250 MB ,位置是在应用的 缓存文件夹 中的一个 特定目录

1.如果显示的媒体是公开的(从未经身份验证的网站、搜索引擎等获取),则应用程序可以将位置更改为外部存储:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

builder.setDiskCache(new ExternalCacheDiskCacheFactory(context));

}

}

2.无论使用内部或外部磁盘缓存,应用程序都可以改变磁盘缓存的大小:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MB

builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));

}

}

3.应用程序还可以改变缓存文件夹在外存或内存上的名字:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

int diskCacheSizeBytes = 1024 * 1024 * 100; // 100 MB

builder.setDiskCache(

new InternalCacheDiskCacheFactory(context, “cacheFolderName”, diskCacheSizeBytes));

}

}

**4.应用程序还可以自行选择 DiskCache 接口的实现,并提供自己的 DiskCache.Factory 来创建缓存。**Glide 使用一个工厂接口来在后台线程中打开 磁盘缓存 ,这样方便缓存做诸如检查路径存在性等的IO操作而不用触发 严格模式 。

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

builder.setDiskCache(new DiskCache.Factory() {

@Override

public DiskCache build() {

return new MyCustomDiskCache();

}

});

}

}

Bitmap pool(位图池)


Glide 使用 LruBitmapPool 作为默认的 BitmapPool 。LruBitmapPool 是一个内存中的固定大小的 BitmapPool,使用 LRU 算法清理。默认大小基于设备的分辨率和密度,同时也考虑内存类和 isLowRamDevice 的返回值。具体的计算通过 Glide 的 MemorySizeCalculator 来完成,与 Glide 的 MemoryCache 的大小检测方法相似。

1.可以在它们的 AppGlideModule 中定制 BitmapPool 的尺寸,使用 applyOptions(Context, GlideBuilder) 方法并配置 MemorySizeCalculator:

@GlideModule

public class MyGlideModule extends AppGlideModule {

@Override

public void applyOptions(Context context, GlideBuilder builder) {

MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)

.setBitmapPoolScreens(3)

尾声

评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。

有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。

一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

{

@Override

public void applyOptions(Context context, GlideBuilder builder) {

MemorySizeCalculator calculator = new MemorySizeCalculator.Builder(context)

.setBitmapPoolScreens(3)

尾声

评论里面有些同学有疑问关于如何学习material design控件,我的建议是去GitHub搜,有很多同行给的例子,这些栗子足够入门。

有朋友说要是动真格的话,需要NDK以及JVM等的知识,首现**NDK并不是神秘的东西,**你跟着官方的步骤走一遍就知道什么回事了,无非就是一些代码格式以及原生/JAVA内存交互,进阶一点的有原生/JAVA线程交互,线程交互确实有点蛋疼,但平常避免用就好了,再说对于初学者来说关心NDK干嘛,据鄙人以前的经历,只在音视频通信和一个嵌入式信号处理(离线)的两个项目中用过,嵌入式信号处理是JAVA->NDK->.SO->MATLAB这样调用的我原来MATLAB的代码,其他的大多就用在游戏上了吧,一般的互联网公司会有人给你公司的SO包的。
至于JVM,该掌握的那部分,相信我,你会掌握的,不该你掌握的,有那些专门研究JVM的人来做,不如省省心有空看看计算机系统,编译原理。

一句话,平常多写多练,这是最基本的程序员的素质,尽量挤时间,读理论基础书籍,JVM不是未来30年唯一的虚拟机,JAVA也不一定再风靡未来30年工业界,其他的系统和语言也会雨后春笋冒出来,但你理论扎实会让你很快理解学会一个语言或者框架,你平常写的多会让你很快熟练的将新学的东西应用到实际中。
初学者,一句话,多练。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值