Android实际开发中的bug总结与解决方法(三)
来源:互联网 发布:淘宝买水果坏了怎么办 编辑:程序博客网 时间:2024/06/18 05:40
Android实际开发中的bug总结与解决方法(三)
解决bug中的总结:Bitmap 内存优化相关
XXXXX项目中相关的bug有2个:
1) 在生成圆角图片的RoundImageView的onDraw()方法中 :bug: bitmap size exceeds VM budget .
2) 在SSQSplashActivity的onCreate()方法中加载欢迎界面的图片时 bug: OutOfMemoryError.
Bitmap 内存优化:
1) 要及时回收Bitmap的内存
Bitmap类的构造方法都是私有的,所以不能直接new出一个Bitmap对象,只能通过BitmapFactory类的各种静态方法来实例化一个Bitmap。
查看BitmapFactory的源代码可以看到,生成Bitmap对象最终都是通过JNI调用方式实现的。所以,加载 Bitmap到内存里以后,是包含两部分内存区域的。简单的说,一部分是Java部分的,一部分是C部分的。
这个Bitmap对象是由Java部分分配的,不用的时候系统就会自动回收了,但是那个对应的C可用的内存区域,虚拟机是不能直接回收的,这个只能调用底层的功能释放。所以需要调用 recycle()方法来释放C部分的内存。
从Bitmap类的源代码也可以看到,recycle()方法里也的确是调用了JNI方法了的。
对于第一个bug:
在RoundImageView控件中采用的生成圆角图片的方法是setXfermode(Mode.SRC_IN)+canvas来实现的,其中在onDraw()方法中共在创建了3个bitmap对象,其中一个是bitmap = b.copy(Bitmap.Config.ARGB_8888, true)的拷贝其实现实是调用的JNI的方法在C底层实现,但是在最后仅仅是将bitmap赋值为null了,如bmp = null;这样的话,可能存在Android系统对java层的bitmap做了回收,而没有用 recycle()方法调用JNI的来彻底回收C部分的内存。
解决办法:生成圆角图片有一个更好的实现方法是:BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)。调用这个方法来产生一个画有一个位图的渲染器(Shader)。该方法实现简单高效,节约内存开销。查看球神的源码中,就是用的这种方法。于是我们将球神中的CircleImageView控件,替换了之前的RoundImageView控件。
2)捕获异常
因为Bitmap是内存消耗大户,为了避免应用在分配Bitmap内存的时候出现OutOfMemory异常以后Crash掉,需要特别注意实例化Bitmap部分的代码。
通常,在实例化Bitmap的代码中,一定要对OutOfMemory异常进行捕获。
尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
然而,可以改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的不同之处在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。
因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
然而,可以改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
decodeStream最大的不同之处在于其直接调用JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了java层的空间。
但是,decodeStream有这么一个缺点:
decodeStream直接拿的图片来读取字节码了, 不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的图片资源,
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。
Bitmap,占用内存的算法如下:
图片的width*height*Config。如果Config设置为ARGB_8888,那么上面的Config就是4。一张480*320的图片占用的内存就是480*320*4 byte。
对于第二个bug:
在欢迎界面加载的图片是720*1280,位深度是24,大小189kb. 在Android中图片占用的内存就是720*1280*4byte. 所以还是比较大的。建议在保证高清线度的前提下,尽量减小的图片资源。
4) 压缩图片
使用BitmapFactory.Options设置inSampleSize就可以缩小图片。属性值inSampleSize表示缩略图大小为原始图片大小的几分之一。如果知道图片的像素过大,就可以对其进行缩小。
那么如何才知道图片过大呢?
方法是:使用BitmapFactory.Options设置inJustDecodeBounds为true后,再使用decodeFile()等方法,并不会真正的分配空间,即解码出来的Bitmap为null,但是可计算出原始图片的宽度和高度,即options.outWidth和 options.outHeight。通过这两个值,就可以知道图片是否过大了。在实际项目中,先获取图片真实的宽度和高度,然后判断是否需要跑缩小。如果不需要缩小,设置inSampleSize的值为 1。如果需要缩小,则动态计算并设置inSampleSize的值,对图片进行缩小。需要注意的是,在下次使用BitmapFactory的 decodeFile()等方法实例化Bitmap对象前,别忘记将opts.inJustDecodeBound设置回false。否则获取的 bitmap对象还是null。
0 0
- Android实际开发中的bug总结与解决方法(三)
- Android实际开发中的bug总结与解决方法(一)
- Android实际开发中的bug总结与解决方法(二)
- Android实际开发中的bug总结与解决方法(一)
- 收集Android实际开发中的bug总结与解决方法(第一节)
- 收集Android实际开发中的bug总结与解决方法(第二节)
- 收集Android实际开发中的bug总结与解决方法(第三节)
- Android开发bug总结
- android学习总结(二)----MVC在实际中的应用
- Fragment实际开发中的总结(一)
- java 实际应用中的实验与总结
- Android实际开发常用框架总结
- Android开发常见bug及解决方法 (一)
- 2014.4.21 实际开发工作中的工作模式的总结
- Android 开发中常见bug 总结
- Android开发之Activity总结(三)
- Django开发过程中的一些bug及解决方法
- android---实际开发中遇到的问题总结
- 一个APP两个程序主入口,两个图标,互不干扰
- cf(思维题)
- 关于Cocos C++ http 有中文参数 服务器接收乱码问题解决!
- 《iOS总结》strong和weak
- Netty4.x中文教程系列 ChannelHandler
- Android实际开发中的bug总结与解决方法(三)
- Inner join,outer join,left join,right join的区别
- datatables显示隐藏列
- solr实战问题集合
- Kotlin: Java 6 废土中的一线希望
- ssh如果对实体进行了修改,但不希望其修改映射到数据库中,修改不要放在service中
- 线索二叉树详解以及代码实现
- 2015-10-30-Android手机屏幕相关知识点
- 杭电1047 An Easy Task - java 解读