请点赞,你的点赞对我意义重大,满足下我的虚荣心。
🔥常在河边走,哪有不湿鞋。或许面试过程中你遇到的问题就在这呢?
🔥关注我个人简介,面试不迷路~
一、组件化在项目中的意义(阿里)
这道题想考察什么?
1.是否了解组件化的作用 与 概念理论?
考察的知识点
1.组件化存在的意义与理论的基本知识
考生应该如何回答
1.组件化有什么意义,没有组件化会出现什么问题?
早期的单一分层模式 问题一:无论分包怎么做,随着项目增大,项目失去层次感,后面接手的人扑街 问题二:包名约束太弱,稍有不注意,就会不同业务包直接互相调用,代码高耦合 问题三:多人开发在版本管理中,容易出现代码覆盖冲突等问题
请看一下图:

所有的代码都写在app模块中不同的包里面,请看一下图:

组件化的意义:不相互依赖,可以相互交互,任意组合,高度解耦,自由拆卸,自由组装,重复利用,分层独立化

此时:app不在是老大,子模块都是小弟
组件化后,所有的module都平起平坐,有人说app的module在组件化中是个壳子,这也是为什么成为app壳工程的原因
同学们思考,如果没有组件化,还是单一: 1.彻底砍掉order子模块,需要多少工作? 2.如何给项目增加一个子模块(钱包)? ........
2.组件 与 组件 的通信方式那些?
方式一 使用 EventBus的方式,缺点是:EventBean维护成本太高,不好去管理: 方式二 使用广播的方式,缺点是:不好管理,都统一发出去了 方式三 使用隐士意图方式,缺点是:在AndroidManifest.xml里面配置xml写的太多了 方式四 使用类加载方式,缺点就是,容易写错包名类名,缺点较少 方式五 使用全局Map的方式,缺点是,要注册很多的对象
方式六 使用 阿里巴巴开源框架 ARouter
二、组件化中的ARouter原理(阿里)
这道题想考察什么?
- 是否了解ARouter真实场景使用,是否理解ARouter原理?
考察的知识点
- ARouter在项目中使用与基本知识
考生应该如何回答
-
请问ARouter是怎么完成 组件与组件之间通信的,请简单描述清楚?
答:
第一步:注册子模块信息到路由表里面去,怎么注册,难道是自己去注册,当然不是,采用编译器APT技术,在编译的时候,扫描自定义注解,通过注解获取子模块信息,并注册到路由表里面去。 第二步:寻址操作,寻找到在编译器注册进来的子模块信息,完成交互即可。
2.能画一张ARouter 通信的示意图吗?
答:
示意图如下:

三、谈一下你对APT技术的理解(美团)
这道题想考察什么?
- 是否了解APT真实场景使用,是否理解APT?
考察的知识点
- APT在项目或开源框架使用与基本知识
考生应该如何回答
1.ARouter采用APT技术,还有那些框架是采用APT技术呀?
答:像butterknife框架,EventBus框架,DataBinding框架,JetPack.Room库 等等 都是采用APT技术来生成代码。
2.APT技术生成代码,有更好的方式么?
答:像butterknife框架,在采用APT生成代码的时候,就是一行一行的拼接 包,类,函数,等方式,拼接而生成的,但是也不要笑话人家的这种方式,这种方式 可读性还是可以的。 像ARouter框架,就是采用JavaPoet技术来生成代码的,JavaPoet是面向对象的思想来生成,不需要一行一行的拼接,更符合开发者思维。
四、谈谈Glide框架的缓存机制设计(B站)
这道题想考察什么?
- 是否了解Glide缓存机制与真实场景使用,是否熟悉Glide缓存机制在工作中的表现是什么?
考察的知识点
- Glide缓存机制的概念在项目中使用与基本知识
考生应该如何回答
1.说说Glide缓存机制?
答:
引入缓存的目的
- 1、减少流量消耗,加快响应速度;
- 2、Bitmap 的创建/销毁比较耗内存,可能会导致频繁GC;使用缓存可以更加高效地加载 Bitmap,减少卡顿。
Glide缓存流程
Glide缓存分为内存缓存和磁盘缓存,其中内存缓存是由弱引用+LruCache组成。
取的顺序是:弱引用、LruCache、磁盘 存的顺序是:磁盘、弱引用、LruCache

**
注意:关于缓存的存取的入口在Engine
这个类中**
内存缓存原理
概述
1、弱引用是由这样一个HashMap维护,key是缓存的key,这个key由图片url、width、height等10来个参数组成;value是图片资源对象的弱引用形式。
Map<Key, ResourceWeakReference> activeEngineResources = new HashMap<>();
2、LruCache是由一个LinkedHashMap维护,根据Lru算法来管理图片。大致的原理是利用linkHashMap链表的特性,把最近使用过的文件插入到列表头部,没使用的图片放在尾部;然后当图片大小到达预先设置的一个阀值的时候 ,按算法删除列表尾部的部分数据。由于篇幅有限,这里不讲解LruCache和DiskLruCache的底层原理,这里推荐一篇 图解LinkedHashMap原理
这是Glide自定义的LruCache
#LruCache
Map<T, Y> cache = new LinkedHashMap<>(100, 0.75f, true);
存取原理 取数据
在内存缓存中有一个概念叫图片引用计数器 ,具体来说是在EngineResource
中定义一个acquired
变量用来记录图片被引用的次数,调用acquire()
方法会让变量加1,调用release()
方法会让变量减1。
获取图片资源是先从弱引用取缓存,拿到的话,引用计数+1;没有的话从LruCache中拿缓存,拿到的话,引用计数也是+1,同时把图片从LruCache缓存转移到弱应用缓存池中;再没有的话就通过EngineJob
开启线程池去加载图片,拿到的话,引用计数也是+1,会把图片放到弱引用。
存数据
很明显,这是加载图片之后的事情。通过EngineJob
开启线程池去加载图片,取到数据之后,会回调到主线程,把图片存到弱引用。当图片不再使用的时候,比如说暂停请求或者加载完毕或者清除资源时,就会将其从弱引用中转移到LruCache
缓存池中。总结一下,就是正在使用中的图片使用弱引用
来进行缓存,暂时不用的图片使用LruCache
来进行缓存的功能;同一张图片只会出现在弱引用
和LruCache
中的一个。
为什么要引入软引用?
1、分压策略,减少Lrucache 中trimToSize
的概率。如果正在remove的是张大图,lrucache正好处在临界点,此时remove操作,将延缓Lrucache的trimToSize
操作; 2 提高效率:弱引用用的是HashMap
,Lrucache用的是LinkedHashMap
,从访问效率而言,肯定是HashMap
更高。
磁盘缓存原理(DiskLruCache)
Glide磁盘缓存策略
-
DiskCacheStrategy.DATA
: 只缓存原始图片; -
DiskCacheStrategy.RESOURCE
:只缓存转换过后的图片; -
DiskCacheStrategy.ALL
:既缓存原始图片,也缓存转换过后的图片;对于远程图片,缓存 DATA和 RESOURCE;对于本地图片,只缓存 RESOURCE; -
DiskCacheStrategy.NONE
:不缓存任何内容; -
DiskCacheStrategy.AUTOMATIC
:默认策略,尝试对本地和远程图片使用最佳的策略。当下载网络图片时,使用DATA
(原因很简单,对本地图片的处理可比网络要容易得多);对于本地图片,使用RESOURCE
。
如果在内存缓存中没获取到数据会通过EngineJob
开启线程池去加载图片,这里有2个关键类:DecodeJob
和EngineJob
。EngineJob
内部维护了线程池,用来管理资源加载,当资源加载完毕的时候通知回调; DecodeJob
是线程池中的一个任务。
磁盘缓存是通过DiskLruCache
来管理的,根据缓存策略,会有2种类型的图片,DATA
(原始图片)和 RESOURCE
(转换后的图片)。磁盘缓存依次通过ResourcesCacheGenerator
、SourceGenerator
、DataCacheGenerator
来获取缓存数据。ResourcesCacheGenerator
获取的是转换过的缓存数据;SourceGenerator
获取的是未经转换的原始的缓存数据;DataCacheGenerator
是通过网络获取图片数据再按照按照缓存策略的不同去缓存不同的图片到磁盘上。
总结(干货)
Glide缓存分为弱引用+ LruCache+ DiskLruCache
,其中读取数据的顺序是:弱引用 > LruCache > DiskLruCache>网络;写入缓存的顺序是:网络 --> DiskLruCache--> LruCache-->弱引用
内存缓存分为弱引用的和 LruCache ,其中正在使用的图片使用弱引用缓存,暂时不使用的图片用 LruCache缓存,这一点是通过 图片引用计数器(acquired变量)来实现的,详情可以看内存缓存的小结。
磁盘缓存就是通过DiskLruCache实现的,根据缓存策略的不同会获取到不同类型的缓存图片。它的逻辑是:先从转换后的缓存中取;没有的话再从原始的(没有转换过的)缓存中拿数据;再没有的话就从网络加载图片数据,获取到数据之后,再依次缓存到磁盘和弱引用。
今天的面试分享到此结束拉~下期在见
网友评论