android图片的优化
Ⅰ Android性能优化-大分辨率图片最佳实践
好久没更新博客了,借着908公司18周年年会这个普(期)天(待)同(红)庆(包)的日子,来说下安卓中的图片与内存的关系。
大家都知道安卓中图片是占用内存的大户,在日常开发中也免不了用到图片,那么图片占用内存与哪些因素有关呢,先直接给结论:
1)与图片分辨率有关;
2)与开发者放的文件目录有关;
3)与图片大小没有半毛钱关系。
举个例子:
以现在主流1080p手机为例,新建一个空的工程,用一张1080*1080像素图片来测试:
将图片放在xxhdpi目录下,测试内存,效果如下:
大家可以接着尝试将图片放到mhdpi目录 或者xhdpi目录下,看下内存占用情况,上面放xxhdpi从图上看大概占4M左右,那么这个值是怎么计算来的:
放xxhpi下图片内存占用 = 1080 *1080 *4 /1024 / 1024 = 4.45M
稍微解释下公式,像素长*宽*一个像素占用的字节数,安卓的色彩模式一个像素占用的字节关系如下表:
也就是说,你在布局文件里随便定义一个imageview,加载一个1080*1080的图片,显示的时候,将按一像素4byte计算内存占拆配昌用。
如果你按照上面的步骤尝试了将图片放到mdpi目录或者xhdpi目录,应该知道结论了,图片占用内存成倍数的变大了,看下放mdpi文件夹下的效果:
如果开发者将同样一张1080*1080像素图片放到mdpi目录下,图片占用内存=(1080*3)*(1080*3)*4 /1024 /1024 = 40M,比之前放xxdpi目录下内存高出了9倍,所以:图片不是乱放的,要谨慎。
现在主流手机分辨率1080p以上,建议大图统一放到xxhdpi目录下管理。
高分辨率图片常见的导致性能缺陷的场景包括:
1)放错图片目录卖基,导致占用内存成倍数增长;
2)限定了高宽的imageview组件,加载了超过该尺寸大小的图片;
3)单色值图片、loading过渡图片、对清晰度要求不高的图片等,强上了大分辨率图片。
这些场景都是在实际开发中遇到过的问题,可能出于设计师的疏忽,可能出于程序猿的随意,修复这些缺陷的成本很低,但是对内存降低的帮助是指数级的,投入产出比这么高的事情,只能说到这里了。
对应的修复手段很明确了:
1)建议图片放xxhpdi目录;
2)限定高宽的imageview,图片最大尺寸不超过该imageview最大承载高宽;
3)简单图片直接下掉,或者压缩下吧,也可以结合业务背景用背景色等替换。
如果你的项目比较小,人肉去找都可以知道哪些是大分旅扒辨率图片,那么检查下使用是否正确。如果你的项目是一个大型客户端项目,人工去找就很尴尬了,是的,我想说python大法好,来个脚本吧,无死角搞定所有大分辨率图片可能导致的性能缺陷:
Ⅱ 在Android开发中,有哪些好的内存优化方式
我的做法是时间换空间,尽量文件化一些占用内存的数据。最典型的就是ListView中的Bitmap,可以参考这个开源组件的实现。 其将Bitmap都本地文件缓存,内存中只保留最近使用的4张图片,在使用中发现还是会偶尔出现OOM,然后我就将其改为完全的读取文件,内存中不保留图片,使用以后都自动回收,由此扩展的数据文件也同样缓存成文件。
除了Bitmap,其他的地方没想到什么能占用这么大内存,网络下载下来的数据文件?需要都留在内存中吗?目前我做的应用,每次请求的数据大小都比较小,每次Http请求下来的数据都把url转换成文件名,然后缓存成文件,在下次Http请求的时候先根据url来预读文件,暂时不用的数据就释放掉。
经常会OOM我觉得就是在Bitmap处理的时候,比如decodeFile,在往界面上加载图片时,不用直接加载原图,可以进行缩放。一张1000*1000的图片要加载到一个100*100的ImageView上,直接加载进来大多数都会OOM,可以先用inJustDecodeBounds
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
拿到这个图片的大小,再算好缩放比例
int scale = 0;
scale = (int)(options.outHeight / (float)size);
if (scale <= 0) {
scale = 1;
}
options.inSampleSize = scale;
options.inJustDecodeBounds = false;
再进行decode。
总之就是尽量时间换空间,实际这个时间是非常非常短的,用户体验内的。
Ⅲ Android性能优化(八)--Android图片内存优化
2个基本原则
既然需要的内存公式已得到,那优化就显而易见了,无非就是减小的这三个参数的值,具体的策略如下:
这里我们将图片分为2种情况来探讨:
图片占用的内存 大小为:
为什么mipmap不在这种情况的考虑范围之内呢?
因为mipmap是Android系统为了避免Launcher Icon变形而添加的资源目录,也就是说,mipmap中的图片不会被缩放。所以Google也不推荐将除Launcher Icon之外的图片放在mipmap目录中。
本地图片通常都是通过Android提供的BitmapFactory来加载的, 这里看几个常用的API:
图片的优化可通过Options参数来实现(Options的介绍可参考 从fresco 看图片优化 :
inPreferredConfig的取值为Bitmap.Config类型(这里只考虑以下几种情况),它是一个枚举类型,用来设置每个像素需要的字节数:
1.jpeg和gif
2.webp
3.png8, png24, png32
网络图片通常我们都是使用开源库进行加载, 所以不需要拿到Bitmap再进行缩放或裁剪。
这时可让后台实现网络图片的裁剪,即:根据图片的请求参数返回合适的尺寸,最大也只需要控件的大小即可。
再大也没意义,不仅浪费流量,还占用内存。
如果你的APP中有很多图片,那么可对图片的宽高根据设备的内存情况进行适当的缩小:
尽量为所有分辨率创建资源 资源匹配分辨率 = 减少不必要的缩放,从而提高UI绘制效率
对于一个多图片的APP来说,图片所占内存的优化是一项必不可少的工作。
总的来说,其优化也就是通过 缩放 和指定 Bitmap.Config的值 来实现的,只是不同位置,不同格式的图片有所差异而已。
https://juejin.im/post/5af84f4b51882542714fdaa9?utm_medium=an&utm_source=weixinqun
Ⅳ Android图片加载及虚化效果
[TOC]
使用如下方式加载图片
会导致OOM,android对于直接通过资源id载入的资源需做cache,下次再需要此资源的时候直接从cache中得到。但这样做也造成了用过的资源都会在内存中,这样的设计不是很适合使用了很多大图片资源的应用,这样累积下来应用的内存峰值是很高的。
当使用诸如
imageView.setBackgroundResource
imageView.setImageResource
BitmapFactory.decodeResource
这样的方法来设置一张大图片时,在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。如果在读取时加上图片的Config参数,可以有效减少加载的内存,从而有效阻止抛OOM异常。
实际使用中,可以针对bitmap做如下操作
RenderScript是Google在API11中引入的类,可看作业android内置的图片处理框架(区别于Glide等图片处理框架,RenderScript注重于图片的处理而不是加载)。RenderScript实际操作基于RenderScript Intrinsics,一些可以帮助RenderScript快速实现各种图片处理的操作类。该类包含诸多操作功能,比如利用ScriptIntrinsicBlur,就可以简单高效地实现高斯模糊效果,可通过参数radius设置虚化的程度。
1920*1080的原始图片未经压缩读取时间可能会超过1s,使用该图片作为背景图片加载时会有明显的卡顿。此时就需要设置BitmapFactory.Options实现对待加载图片的压缩。可参照 https://blog.csdn.net/u012124438/article/details/66087785 逐步优化Bitmap加载。对于加载图片较多较频繁的功能,建议使用第三方的图片加载框架,如Glide或者Picasso。
需要注意的是,此处doBlur有两个重载,可根据需要设置图片的缩放比例.这种方式和前文通过BitmapFactory.Options设置Bitmap取样格式的效果是一致的,都是为了减小Bitmap加载的资源消耗,提高加载效率。
Ⅳ Android性能优化总结
常用的Android性能优化方法:
一、布局优化:
1)尽量减少布局文件的层级。
层级少了,绘制的工作量也就少了,性能自然提高。
2)布局重用 <include标签>
3)按需加载:使用ViewStub,它继承自View,一种轻量级控件,本身不参与任何的布局和绘制过程。他的layout参数里添加一个替换的布局文件,当它通过setVisibility或者inflate方法加载后,它就会被内部布局替换掉。
二、绘制优化:
基于onDraw会被调用多次,该方法内要避免两类操作:
1)创建新的局部对象,导致大量垃圾对象的产生,从而导致频繁的gc,降低程序的执行效率。
2)不要做耗时操作,抢CPU时间片,造成绘制很卡不流畅。
三、内存泄漏优化:
1)静态变量导致内存泄漏 比较明显
2)单例模式导致的内存泄漏 单例无法被垃圾回收,它持有的任何对象的引用都会导致该对象不会被gc。
3)属性动画导致内存泄漏 无限循环动画,在activity中播放,但是onDestroy时没有停止的话,动画会一直播放下去,view被动画持有,activity又被view持有,导致activity无法被回收。
四、响应速度优化:
1)避免在主线程做耗时操作 包括四大组件,因为四大组件都是运行在主线程的。
2)把一些创建大量对象等的初始化工作放在页面回到前台之后,而不应该放到创建的时候。
五、ListView的优化:
1)使用convertView,走listView子View回收的一套:RecycleBin 机制
主要是维护了两个数组,一个是mActiveViews,当前可见的view,一个是mScrapViews,当前不可见的view。当触摸ListView并向上滑动时,ListView上部的一些OnScreen的View位置上移,并移除了ListView的屏幕范围,此时这些OnScreen的View就变得不可见了,不可见的View叫做OffScreen的View,即这些View已经不在屏幕可见范围内了,也可以叫做ScrapView,Scrap表示废弃的意思,ScrapView的意思是这些OffScreen的View不再处于可以交互的Active状态了。ListView会把那些ScrapView(即OffScreen的View)删除,这样就不用绘制这些本来就不可见的View了,同时,ListView会把这些删除的ScrapView放入到RecycleBin中存起来,就像把暂时无用的资源放到回收站一样。
当ListView的底部需要显示新的View的时候,会从RecycleBin中取出一个ScrapView,将其作为convertView参数传递给Adapter的getView方法,从而达到View复用的目的,这样就不必在Adapter的getView方法中执行LayoutInflater.inflate()方法了。
RecycleBin中有两个重要的View数组,分别是mActiveViews和mScrapViews。这两个数组中所存储的View都是用来复用的,只不过mActiveViews中存储的是OnScreen的View,这些View很有可能被直接复用;而mScrapViews中存储的是OffScreen的View,这些View主要是用来间接复用的。
2)使用ViewHolder避免重复地findViewById
3)快速滑动不适合做大量异步任务,结合滑动监听,等滑动结束之后加载当前显示在屏幕范围的内容。
4)getView中避免做耗时操作,主要针对图片:ImageLoader来处理(原理:三级缓存)
5)对于一个列表,如果刷新数据只是某一个item的数据,可以使用局部刷新,在列表数据量比较大的情况下,节省不少性能开销。
六、Bitmap优化:
1)减少内存开支:图片过大,超过控件需要的大小的情况下,不要直接加载原图,而是对图片进行尺寸压缩,方式是BitmapFactroy.Options 采样,inSampleSize 转成需要的尺寸的图片。
2)减少流量开销:对图片进行质量压缩,再上传服务器。图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩。bitmap.compress(Bitmap.CompressFormat.PNG,100,bos);
七、线程优化:
使用线程池。为什么要用线程池?
1、从“为每个任务分配一个线程”转换到“在线程池中执行任务”
2、通过重用现有的线程而不是创建新线程,可以处理多个请求在创建销毁过程中产生的巨大开销
3、当使用线程池时,在请求到来时间 ,不用等待系统重新创建新的线程,而是直接复用线程池中的线程,这样可以提高响应性。
4、通过和适当调整线程池的大小 ,可以创建足够多的线程以使处理器能够保持忙碌状态,同时还可以防止过多线程相互竞争资源而使应用程序耗尽内存或者失败。
5、一个App里面所有的任务都放在线程池中执行后,可以统一管理 ,当应用退出时,可以把程序中所有的线程统一关闭,避免了内存和CPU的消耗。
6、如果这个任务是一个循环调度任务,你则必须在这个界面onDetach方法把这个任务给cancel掉,如果是一个普通任务则可cancel,可不cancel,但是最好cancel
7、整个APP的总开关会在应用退出的时间把整个线程池全部关闭。
八、一些性能优化建议:
1)避免创建过多对象,造成频繁的gc
2)不要过多使用枚举,枚举占用的空间比整型大很多
3)字符串的拼接使用StringBuffer、StringBuilder来替代直接使用String,因为使用String会创建多个String对象,参考第一条。
4)适当使用软引用,(弱引用就不太推荐了)
5)使用内存缓存和磁盘缓存。
Ⅵ Android图片压缩与优化的几种方式
1.使用的图片最好用png格式
2.如果你的图片仍然大的话可以在项目里面点击右键选择convert to Webp,转成webp格式图片可以变小很多!
Ⅶ android 中图片太大,导致加载特别慢怎么办
图片不会太大,如果加载过慢或加载不出来可能是以下问题:
手机装的软件过多,储存空间不足
网速过慢
手机本身配置落后
可以尝试长按图片,然后保存到手机,在相册中查看
请采纳,谢谢