Android-Daily-Interview
Android-Daily-Interview copied to clipboard
2019-08-01:如何处理大图的加载?
1.通过第三方软件加载。 2.通过压缩工具压缩。 3.加载缓存方式。
具体压缩工具,有哪些推荐的呢?大神
把图片处理成webp格式,或者用Luban压缩压缩图片
1、首先确定大图的用途,精度需求: a)完整显示,对精度要求不高,图片本身就很大 b)对精度需求比较高,不需要完整显示 2、解决方案 a)针对第一种的处理图片本身,按需加载(根据显示设备本身大小进行缩放),降低精度加载(改变图片模式,如将ARGB8888改成RGB565,ARGB4444),修改图片格式(png改成webp,jpg) b)第二种的一般采用局部加载,主要要用到的是BitmapRegionDecoder这个类decodeRegion的方法,读取图片指定大小的数据,然后通过移动来动态改变显示区域的图片
在项目中统一图片库,对不同性能的机型做好加载策略(使用不同的Bitmap.Config加载图片,不同的压缩程度)。 在加载图片后也不能放松警惕,需要对所有图片进行统一监控: 超大图监控 图片是否超过view宽高,消耗不必要的内存 对超大图进行局部加载 (楼上有对此对对策) 重复图片监控 在开发过程中使用hprof分析工具查找重复bitmao,对代码进行优化 图片总内存监控 对应用内图片总内存进行统计,根据应用使用环境排查隐患
上面总结的很好,我说一种应用场景下的解决方案。 recycleview 或者 listview 等列表页中加载大图,为防止,浏览卡顿以及OOM。所以:1、懒加载(延迟加载)+异步线程,并配合第三方图片框架(Glide、Picasso、Fresco等)、luban 压缩图片。 2、LruCache缓存机制读取图片 配合 第一步。
我也分享下:
- 首先分清你要做什么,是否支持缩放。以此来确定图片的宽高。如果只是显示,没必要把图片宽高弄得太大,如果要做类似世界地图的效果,肯定是要移动和缩放的,这种一般图片宽高会比较大。然后我们分情况说。
- 一般加载图片,宽高只要跟控件宽高差不多,甚至小一些都是可以的。
- 图片尽量使用软引用,较大的图片可以通过bitmapFactory缩放后再使用,并及时recycler。
- 加载巨图时不要使用setImageBitmap或setImageResourse或BitmapFactory.decodeResource,这些方法拿到的都是bitmap的对象,占用内存较大。可以用BitmapFactory.decodeStream方法配合BitmapFactory.Options进行缩放
- 加载超大宽高的图片。这里我没做过,但是之前看过类似的效果,原理也简单的了解了一下。就是分区块加载,比如先加载其中的某一块,用户移动时再加载其他区块。网上有一个不错的库BitmapRegionDecoder。
- 一般加载图片,宽高只要跟控件宽高差不多,甚至小一些都是可以的。
首先确定需求是否大图可以缩放,如果需要缩放一般图片的宽高都会挺大,如果只是显示就没有必要弄得太大。
- 如果加载一般的图片,宽高就跟控件宽高差不多。 i. 图片尽量使用软引用,较大的图片可以通过bitmapFactory缩放后在使用,并及时recycle。 ii. 加载巨图时不要使用setImageBitmap或setImageResourse或BitmapFactory.decodeResourse,这些方法拿到的都是bitmap的对象,占用内存较大。可以用BitmapFactory.decodeStream方法配合BitmapFactory.Options进行缩放
- 加载超大宽高的图片就是分区加载,主要要用到的是BitmapRegionDecoder这个类decodeRegion的方法,读取图片指定大小的数据,然后通过移动来动态改变显示区域的图片
1.对于本地大图,可以将png格式的转化为webp格式的 2.对于网络大图,利用options对图片进行压缩,如果加载的图片很多,需要Lrucache对图片进行缓存处理 3.对于超大型图片,可以局部加载,当用户移动时,再去进行加载。
对于超大类型的图片如果要保证精度和体验,可以采用瓦片地图的方案。
先通过BitmapFactory.Options 设置inJustDecodeBounds 不占用内存来获取图片信息 判断是否为大图 根据使用场景计算缩放比较 inJustDecodeBounds设置为false 传递inSampleSize缩放比例压缩图片