ITPub博客

首页 > 移动开发 > ANDROID > 2020阿里大佬总结面试题系列!大厂面试之图片(含答案+学习笔记)

2020阿里大佬总结面试题系列!大厂面试之图片(含答案+学习笔记)

原创 ANDROID 作者:yilian 时间:2020-04-11 14:18:06 0 删除 编辑

作者:爱雨浮龙

一、图片

  1、图片库对比
  2、LRUCache原理
  3、图片加载原理
  4、自己去实现图片库,怎么做?
  5、Glide源码解析
  6、Glide使用什么缓存?
  7、Glide内存缓存如何控制大小?

参考答案:

1、图片库对比

Picasso Glide Fresco

Picasso 毕加索 Square

   Picasso 没有实现本地缓存功能,交给了 Square 的另外一个网络库 okhttp 去实现,
这样的好处是可以通过请求 Response Header 中的 Cache-Control 及 Expired 控制图片的过期时间。
  • 使用简单,代码简洁
  • Square其他类库搭配兼容性好, Retrofit OkHttp

缺点:

  • 功能简单 图片加载
  • 性能(加载速度等等)较( GlideFresco)差
  • 自身没有实现"本地缓存"

Glide Google 开源

  支持 Gif WebP Video
  生命周期继承
  高效缓存策略
  • 支持 MemoryDisk缓存
  • Picasso只会缓存原始尺寸图片,而 Glide缓存时多种规格
  • 内存开销小,默认  RGB_565Picasso默认是 ARGB_8888

缺点:

  • 使用方法复杂,实现方法较多
  • 使用比 Fresco简单,但性能(加载&缓存)却比不上 Fresco

Fresco Facebook

  • 大大减少 OOM,底层使用 C++技术解决图片缓存问题
  • 使用加单,几乎全部功能都能在 xml上定制

缺点:

  • 用法变得更加复杂
  • 依赖包更大了  2~3M
  • 底层 C++,阅读源码困难

对比项 Picasso Glide Fresco
地址 github.com/square/pica… github.com/bumptech/gl… github.com/facebook/fr…
发布时间 2013年5月 2014年9月 2015年5月
是否支持gif false true true
是否支持webP true true true
视频缩略图 false true true
大小 100k 500 KB 2~3M
加载速度
Disk+Men Cache true true true
Easy of use low mediun difficult
star 13160 14709 12444
开发者 Square主导 Google主导 Facebook主导

详细属性对比

对比项 Glide Fresco
配置 compile ‘com.github.bumptech.glide:glide:XXX.XXX’ compile 'com.facebook.fresco:fresco:XXX.XXX
初始化 直接使用 Fresco.initialize(this);
layout 普通ImageView 独有的SimpleDraweeView
圆角, 圆形 需要自己实现圆角,继承自BitmapTransformation操作bitmap对象实现 通过RoundingParams设置参数
缓存 Glide内存和磁盘缓存 三级缓存,分别是 Bitmap缓存,未解码图片缓存, 文件缓存。
缓存图像大小 Glide则会根据ImageView控件尺寸获得对应的大小的bitmap来展示,从而缓存也可以针对不同的对象:原始图像(source),结果图像(result) 缓存原始图像
加载策略 Glide只有占位图 先加载小尺寸图片,再加载大尺寸的
加载进度 false true
  Bitmap myBitmap = Glide.with(上下文)  
      .load(url)  
      .asBitmap() //必须    
      .get()
  //同样在DataSubscriber中获取
  FileBinaryResource resource = (FileBinaryResource) Fresco.getImagePipelineFactory().getMainFileCache().getResource(new SimpleCacheKey(url));
  if (resource != null && resource.getFile() != null) {           
      setImage(ImageSource.uri(Uri.fromFile(resource.getFile())));
  }

2、LRUCache原理

LruCache DiskLruCache

LruCache是Android 3.1所提供的一个缓存类 DisLruCache目前在 Android还不是 Android SDK的一部分,但 Android官方文档推荐使用该算法来实现硬盘缓存。

LinkedHashMap 它使用了一个双向链表来存储 Map中的 Entry顺序关系,这种顺序有两种,一种是 LRU顺序,一种是插入顺序

put()重要的就是在添加过缓存对象后,调用 trimToSize()方法,来判断缓存是否已满,如果满了就要删除近期最少使用的算法。

trimToSize()方法不断地删除 LinkedHashMap中队头的元素,即近期最少访问的,直到缓存大小小于最大值

LruCache中维护了一个集合 LinkedHashMap,该 LinkedHashMap是以访问顺序排序的。当调用 put()方法时,就会在结合中添加元素,并调用 trimToSize()判断缓存是否已满,如果满了就用 LinkedHashMap的迭代器删除队头元素,即近期最少访问的元素。当调用 get()方法访问缓存对象时,就会调用 LinkedHashMapget()方法获得对应集合元素,同时会更新该元素到队尾。

3、图片加载原理

4、自己去实现图片库,怎么做?

  图片的同步加载
  图片的异步加载
  图片压缩
  内存缓存
  磁盘缓存
  网络拉取

5、Glide源码解析

  RequestManager with(Context context)
  RequestManager with(android.app.Activity)
  RequestManager with(android.app.Fragment)
  RequestManager with(android.support.v4.app.Fragment)
  RequestManager with(android.support.v4.app.FragmentActivity)

无论使用什么参数,最终都会进入如下三个方法创建  RequestManager

  RequestManager fragmentGet(Context context, android.app.FragmentManager fm);
  RequestManager supportFragmentGet(Context context, 
  android.support.v4.app.FragmentManager fm);
  RequestManager getApplicationManager(Context context);

结论:

  • Activity--FragmentManager--RequestManagerFragment--RequestManager,所以一个  Activity 对应一个  RequestManager
  • 一个  Fragment对应一个 RequestManager
  • Activity 包含 FragmentFragment包含  Fragment,若分别创建 Glide请求是并不会只创建一个  RequestManager
  • 子线程发起 Glide请求或传入对象为 ApplicationContext,则使用全局单例的  RequestManager

创建  RequestBuilderload方法有很多:

  RequestBuilder<Drawable> load(@Nullable Bitmap bitmap);
  RequestBuilder<Drawable> load(@Nullable Drawable drawable);
  RequestBuilder<Drawable> load(@Nullable String string);
  RequestBuilder<Drawable> load(@Nullable Uri uri);
  RequestBuilder<Drawable> load(@Nullable File file);
  RequestBuilder<Drawable> load(@RawRes @DrawableRes @Nullable Integer resourceId);
  RequestBuilder<Drawable> load(@Nullable URL url);
  RequestBuilder<Drawable> load(@Nullable byte[] model);
  RequestBuilder<Drawable> load(@Nullable Object model);

看看有这么多重载方法,没一个都代表不同的加载源。 除此之外还有两个特殊的方法:

  RequestBuilder<File> downloadOnly();
  RequestBuilder<File> download(@Nullable Object model);

再创建  RequestManager 时会先创建一个不可见的 Fragment,通过 FM加入到当前页面,用这个不可见的 Fragment即可检测页面的生命周期。

Request 主要的实现类有三个:

  SingleRequest
  ThumbnailRequestCoordinator
  ErrorRequestCoordinator

6、Glide使用什么缓存?

  BitmapPool 大小通过 MemorySizeCalculator 设置;
  使用 LRU 算法维护 BitmapPool ;
  Glide 会根据 Bitmap 的大小与 Config 生成一个 Key;
  Key 也有自己对应的对象池,使用 Queue 实现;
  数据最终存储在 GroupedLinkedMap 中;
  GroupedLinkedMap 使用哈希表、循环链表、List 来存储数据。

7、Glide内存缓存如何控制大小?

一种是 Resource缓存,一类是 Bitmap缓存。

Resource缓存: 图片从网络加载,将图片缓存到本地,当需要再次使用时,直接从缓存中取出而无需再次请求网络。

Glide在缓存 Resource使用三层缓存,包括:

  一级缓存:缓存被回收的资源,使用LRU算法(Least Frequently Used,最近最少使用算法)。当需要再次使用到被回收的资源,直接从内存返回。
  二级缓存:使用弱引用缓存正在使用的资源。当系统执行gc操作时,会回收没有强引用的资源。使用弱引用缓存资源,既可以缓存正在使用的强引用资源,也不阻碍系统需要回收无引用资源。
  三级缓存:磁盘缓存。网络图片下载成功后将以文件的形式缓存到磁盘中。

Bitmap缓存 通过 Bitmap压缩质量参数: Glide默认使用 RGB_565,比系统默认使用的 ARGB_8888节省一半的资源,但 RGB_565无法显示透明度。

Bitmap缓存算法:

  在Glide中,使用BitmapPool来缓存Bitmap,使用的也是LRU算法。
  当需要使用Bitmap时,从Bitmap的池子中取出合适的Bitmap,若取不到合适的,则再新创建。
  当Bitmap使用完后,不直接调用Bitmap.recycler()回收,而是放入Bitmap的池子。

8.Fresco 源码分析

  初始化Fresco。
  获取DataSource。
  绑定Controller与Hierarchy。
  从内存缓存/磁盘缓存/网络获取图片,并设置到对应的Drawable层。


  缓冲缓存层:由BufferedDiskCache实现,提供缓冲功能。
  文件缓存层:由DiskStorageCache实现,提供实际的缓存功能。
  文件存储层:由DefaultDiskStorage实现,提供磁盘文件读写的功能。
  DiskStorageCache:实现了FileCache接口与DiskTrimmable接口是缓存的主要实现类。
  DefaultDiskStorage:实现了DiskStorage接口,封装了磁盘IO的读写逻辑。
  BufferedDiskCache:在DiskStorageCache的基础上提供了Buffer功能。

private static final String CONTENT_FILE_EXTENSION = ".cnt"; private static final String TEMP_FILE_EXTENSION = ".tmp";

未解码图片内存缓存:由 EncodedImage描述真正的缓存对象。 已解码图片内存缓存:由 BitmapMemoryCache描述真正的缓存对象。

作为一个Android程序员,要学的东西有太多太多了,对于进阶这条路而言,学习是会有回报的!

你把你的时间投资在学习上,就意味着你可以收获技能,更有机会增加收入。

分享我的Android学习PDF大全来学习,这份Android学习PDF大全真的包含了方方面面了,内含Java基础知识点、Android基础、Android进阶延伸、算法合集等等

我的这份学习合集,可以有效的帮助大家掌握知识点。

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

无论是大大小小的面试,要想心理不慌,刷题必不可少!平时写文章更新有点慢,给大家看看我的大厂面试题合集!

计算机基础面试题、数据结构和算法面试题、Java面试题、Android面试题、其他扩展面试题、非技术面试题总共五个章节354页。

面试时 HR也是不可以忽略的环节,我们经常也会遇到很多关于简历制作,职业困惑、 HR经典面试问题回答等有关面试的问题。

有全套简历制作、春招困惑、HR面试等问题解析参考建议。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/69952849/viewspace-2685599/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
人生的长跑中,跑得最远的人,可能不是跑得最快的人,而是规划了最佳行程的人 Android学习也是如此,分享Android学习内容、面试精选等,关注我,需要学习计划大纲和学习内容:xx13414521

注册时间:2019-11-05

  • 博文量
    175
  • 访问量
    146018