Android知识整理安卓资源收集Android

Android图片加载问题分析

2016-10-31  本文已影响648人  黄怡菲

下图是一个客户端图片加载模块常见的处理流程。

imagepipeline.png

本文以UniversalImageLoader为例分析了这一流程,然后分析了Fresco的优势和问题,最终推荐大家使用Glide。

从UniversalImageLoader分析图片加载中需要处理的问题

网络

主要用于下载网络图片,在UIL中是将图片地址变为InputStream。UIL支持多种类型来源的图片显示,包括:

缓存

解码

显示

实现接口BitmapDisplayer可以自定义显示效果,已实现的包括:带描边的圆形、渐入、圆角矩形(不能四个角分别指定)等。

某些设计可能会出现两个角圆角、另外两个直角的特殊裁剪模式。自己实现这类Displayer时,不要生成一个新的Bitmap,定义一个Drawable会更高效。因为生成新的Bitmap会引起内存分配和回收,从而使GC更加频繁,而Drawable只是在绘制时会使用很少的计算资源。可以参考源码中RoundedBitmapDisplayer。

多线程

图片的下载和解码都需要再后台线程中处理,而且为了提高效率,一般都使用多个线程分别进行解码和网络请求。

共有三个Executor,分别用于

已缓存的图片主要占用计算资源,未缓存的图片则主要占用网络资源,所以不应该在一个Executor中竞争。可以分别指定Executor的线程数量,UIL默认为3个。

监听

UIL向外提供了两类监听:ImageLoadingListener和ImageLoadingProgressListener

PauseOnScrollListener主要用于,在列表滚动时暂停图片加载,但在现在的RecyclerView中无法使用。需要自己使用ImageLoader#pauseImageLoader#resume

了解了UIL是如何处理图片加载的问题之后,其他的第三方库也都是大同小异,下面再介绍下Fresco和Glide。

Fresco的优势和问题

Fresco在解决图片加载问题上的思路和其他框架有很大的不同。它最大的问题有两个:

相比UIL,它的优点主要包括:

更多关于Fresco的特点可以参考Android图片加载开源库深度推荐,安利Fresco

缓存和网络:Image Pipeline

在5.0系统以下,Image Pipeline 使用 pinned purgeables 将Bitmap数据避开Java堆内存,存在ASHMEM中。这要求图片不使用时,要显式地释放内存。SimpleDraweeView自动处理了这个释放过程,所以没有特殊情况,尽量使用SimpleDraweeView。

显示

修改图片的显示效果需要使用DraweeHolder,它不仅能控制图片的显示,还可以处理View的Touch事件。默认支持圆角和圆形。

另一个控制图片显示的方法是在Postprocessor中修改Bitmap,但效率很低。

监听

Glide是个不错的选择

优点

可参考Glide相关文章了解怎么通过自定义的GlideModule优化加载的图片。本文也提供给了参考代码,在代码中引入七牛裁图服务,同时也可体验10种GPU变化的特效。

关于Transformation和BitmapImageViewTarget的使用

关于Bitmap的回收机制

系统的Bitmap内存管理机制随着Android系统的演进可以分为三个阶段,关于这部分可以参考官网文章Managing Bitmap Memory

如有兴趣,可参考笔者的另一篇文章了解《Glide如何通过引用计数复用Bitmap》

Android系统使用的内存除了native heapJava heap以外,还有ASHMEM。在5.0之前可以通过Options#inPurgeable将Bitmap的数据存储在ASHMEM中,从而不占据一个进程的内存上限。

BitmapFactory.Options = new BitmapFactory.Options();
options.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length, options);

关于Android系统中三种内存的和Bitmap的关系可以参考Introducing Fresco: A new image library for Android

参考文章

上一篇下一篇

猜你喜欢

热点阅读