Android 加载超大图(原图)分析

众所周知,Android的ImageView不支持加载大图(高分辨率),会直接报错,如果不是特别大的图片,也可以选择使用WebView来加载,并且直接可以实现手势方法缩小平移等效果,但是如果图片特别长,比如长文章导出的图片比如这个LINK, 如果使用WebView,放大后细节丢失特别多,字都没法看清楚了。看了看市面上的APP,对这种大图,有些是使用ImageView来实现的(eg.微博,脉脉),当然这个ImageView不会直接去加载整个图片,有些是使用View来加载(华为自带图库),通过Draw来绘制图片。主要的方式基本上都是通过BitmapRegionDecoder来分块加载图片。

本着不重复制造轮子的原则,就满Github翻,,最终找打一个比较靠谱的。。。

https://github.com/kareluo/IntensifyImageView

我给fork了一下:

https://github.com/qduningning/IntensifyImageView

https://github.com/kareluo/IntensifyImageView/raw/master/screenshot/single_preview.gif

使用也比较简单:

IntensifyImageView imageView = (IntensifyImageView)findViewById(R.id.intensify_image);

// 通过流设置
imageView.setImage(InputStream inputStream);

// 通过文件设置
imageView.setImage(File file);

// 通过文件路径设置
imageView.setImage(String path);

看了下源码,这个库没有继承ImageView而是直接继承了View,其中实现主要用到了:

图片分块加载:这里用到了BitmapRegionDecoder对图片进行分块,实际上展示的效果就是,实际上展示的图片是很多个小块拼凑而成的(IntensifyImageView的onDraw方法实际上是draw了当前可见的那些drawable块),每个小块划分的原则是,图片原始比例时,宽和高最大为300(边缘处的不足300的会小一些)。

LruCache: 进行RegionDecode还是挺耗时间的,为了加快加载的速度,这个库复用了之前已经加载过的块,并且也能匹配到更高分辨率的块。如果没有的话,该次刷新不会显示该块(因为每次刷新都会绘制一个底层,这个底层是整张图,并且采样率很低,这样的话即使Lrucache没有当前要绘制的小块,也不会出现空白块的情况),而是放在后台线程去加载这次绘制没有拿到缓存的块,加载成功后,再次绘制界面。

手势 :主要就是使用了ScaleGestureDetectorGestureDetector,前者用于处理缩放手势,后者用于处理其余手势,如移动,快速滑动,点击,双击,长按等。

其他详细介绍查看作者的博客:

http://kareluo.github.io/2015/12/27/Android-Picture-Preview/