最近在xoom上开发应用,碰到ui设计都是使用图片,而且是多个activity。开始没觉得怎么样,就开始做呗。等做完了,开始在前三个activity运行没问题,一切ok。但在最后一个activity里,会经常出现oom(out of memory),由于在最后一个activity,需要打开一个pdf,然后render,随着multi-touch,reander的pdf页缩放,由于reander的图片本身就比较大(比如,如果pdf放大到当前屏幕的两倍,pdf图片占用的内存为1280*800*4*2/(1024*1024),约等于8m),而且由于为了视觉上感受好,会在其中缓存图片(为了不让用户在使用过程中感受操作有停滞感),所以总是导致oom异常。
oh,my god!最怕碰到这种情况,android对于内存heap size限制让人比较崩溃,ios虽然也号称一个应用有内存限制,但是在实际使用中一个应用使用的内存往往可以超过100m,所以还是挺容易做一个性能满意的应用程序。
我的应用到底哪些地方使用了这么多内存,因为android3.0默认heap size为48m,按道理来说还是可以接受的,怎么应用没跑几下就oom呢?没办法,只能通过ddms来分析,在ddms中“update heap”-》“cause gc”,来查看应用的内存使用情况,发现每进入一个activity,1-byte array(byte[], boolean[])的值总是会相应的增加,到最后一个activity的时候啥都不干,heap size已经快30m了,oh。。。怎么会这样。。。冷静冷静。。。通过分析,1-byte array就是bitmap的占用空间,这就说明不断有新的bitmap在内存中。由于ui使用了很多图片,比如大背景图,按钮图片等等,看来是这些图片都会存在内存中,即使当前activity已经销毁进入下一个activity,前一个activity的图片资源也没有销毁。
原因找到了,但不是太想得通。因为在onCreate中我用mBtn.setBackgroundResource(R.drawable.splash)为控件设置背景图,然后在onDestroy中会用((BitmapDrawable)mBtn.getBackground()).setCallback(null)清理背景图。按道理来说图片资源应该已经清理掉了的。百思不得其解,仔细看Bitmap的源代码,它其实起的作用是销毁java对象BitmapDrawable,而android为了提高效率,Bitmap真正的位图数据是在ndk中用c写的,所以用setCallback是不能销毁位图数据的,应该调用Bitmap的recycle()来清理内存。
所以想当然的在onDestroy加上((BitmapDrawable)mBtn.getBackground()).getBitmap().recycle(),这样跑下来,内存情况很理想,不管在哪个activity中,使用的资源仅仅是当前activity用到的,就不会象之前到最后一个activity的时候,所有之前使用的资源都累积在内存中。在每个activity资源和class等使用的内存都在10m左右,已经很理想了(当然如果是在android低版本比如1.5,16时还是不行的,这得重新构架应用),可以为显示pdf预留了比较多内存了。
但新的问题又出现了,当返回之前的activity时,会出现“try to use a recycled bitmap"的异常。这真是按了葫芦起了瓢啊,内心那个沮丧。。。没办法,继续分析。看来是后加上recycle引起的, 位图肯定在内存中有引用,在返回之前的activity时,因为位图数据其实已经被销毁了,所以才造成目前的情况。在看了setBackgroundResource的源码以后,恍然大悟,android对于直接通过资源id载入的资源其实是做了cache的了,这样下次再需要此资源的时候直接从cache中得到,这也是为效率考虑。但这样做也造成了用过的资源都会在内存中,这样的设计不是很适合使用了很多大图片资源的应用,这样累积下来应用的内存峰值是很高的。看了sdk后,我用:
Bitmap bm = BitmapFactory.decodeResource(this.getResources(), R.drawable.splash);
BitmapDrawable bd = new BitmapDrawable(this.getResources(), bm);
mBtn.setBackgroundDrawable(bd);
来代替mBtn.setBackgroundResource(R.drawable.splash)。
销毁的时候使用:
BitmapDrawable bd = (BitmapDrawable)mBtn.getBackground();
mBtn.setBackgroundResource(0);//别忘了把背景设为null,避免onDraw刷新背景时候出现used a recycled bitmap错误
bd.setCallback(null);
bd.getBitmap().recycle();
这样调整后,避免了在应用里缓存所有的资源,节省了宝贵的内存,而其实这样也不会造成太大效率问题,毕竟重新载入资源是非常快速,不会对性能造成很严重的影响,在xoom里我没有感受到和之前有什么区别。
总之,在android上使用大量位图是个比较痛苦的事,内存限制的存在对应用是个很大的瓶颈。但不用因噎费食,其实弄明白了它里面的机制,应用可以突破这些限制的。这只是其中的一种处理方法,还可以考虑BitmapFactory.Options的inSampleSize来减少内存占用。
感谢:http://blog.csdn.net/micro_rat/article/details/6307067
相关推荐
Android 中加载大图片时内存溢出的...可以使用 BitmapFactory.Options、recycle() 方法、Java 中的内存优化技术、Android 中的内存优化技术、JNI 技术、避免使用大图片和缓存技术来减少内存的消耗,从而避免内存溢出。
这个功能在电商应用或者阅读类应用中很常见,用户下拉时图片会放大,松手后图片恢复原状,增加用户的互动体验。 首先,我们需要理解ScrollView的工作原理。ScrollView是LinearLayout的一个子类,它只允许一个直接的...
很多情况下,我们使用图片加载库就是为了加载网络图片。网络操作是一个很复杂的东西。试想一下,如果没有图片加载库,我们就要手动去下载图片,缓存图片,最后再从文件里面读取bitmap并设置到Imageview里面。这还算好...
在Android开发中,图片浏览是常见的功能之一,尤其在社交应用、电商应用或者任何涉及到多媒体内容展示的应用中。本文将详细讲解如何实现Android图片浏览点击放大的功能,并结合提供的源代码进行深入解析。 首先,...
3. **图片缩放**:在Android中,图片的缩放通常涉及到Matrix的使用。Matrix是一个二维变换矩阵,可以用来执行旋转、平移、缩放等操作。我们需要根据缩放比例更新Matrix,并调用ImageView的setImageMatrix()方法来...
在Android平台上,框选图片中的一部分并截取是一项常见的需求,比如在应用中实现自定义截图功能、编辑图片或者在图像处理中选择特定区域。这个功能涉及到多个Android SDK中的类和方法,包括图像处理、视图操作以及...
综上所述,“GalleryDemo”示例涵盖了Android中图片放大、缩小和滑动的关键技术,包括手势识别、矩阵变换、视图状态管理等多个方面。理解并掌握这些知识点对于开发交互丰富的图像应用至关重要。
本篇文章将详细探讨如何在Android应用中使用`GridView`和`ViewPager`来优化图片显示,避免内存溢出。 首先,我们需要理解为什么在Android上显示大量图片会引发OOM。当一个应用占用的内存超过系统分配的最大值时,就...
本项目中使用的是一种名为DES(Data Encryption Standard)的加密算法。DES是一种对称加密算法,它使用相同的密钥进行加密和解密,具有速度快、安全性适中的特点。在Android中,可以使用Java Cryptography ...
1. **异步加载库的选择**:Android社区中有多个成熟的库可以帮助我们实现图片异步加载,例如Universal Image Loader、Picasso、Glide等。这些库提供了方便的API,可以轻松地在ListView中加载网络图片或本地资源图片...
在加密图片时,我们可以在原始数据中随机插入一些无关的字节,使得即使获取了加密后的数据,没有正确的“混入”规则也无法还原原图。这种方法可以进一步提高数据的安全性,防止针对AES等标准加密方式的攻击。 在...
添加后,记得同步项目,这样就可以在代码中使用`GIFView`了。 3. **使用GIFView显示GIF**:在布局XML文件中,添加`GIFView`组件: ```xml <com.daimajia.android.gif.GIFView android:id="@+id/gif_view" ...
在Android应用开发中,创建一个类似微信的图片选择器是一个常见的需求,这涉及到用户界面设计、图片处理和文件管理等多个方面。"Android-Android仿微信的图片选择器带裁剪功能支持圆形和方形裁剪"这个项目就是这样一...
在Android开发中,动态添加图片是一项常见的需求,例如在创建社交动态、编辑个人资料或实现图片选择器等场景。本文将深入探讨如何在Android应用中实现动态添加图片,并结合提供的`multiimagechooser-master`项目进行...
在Android开发中,GridView是一种常见的布局控件,用于展示多行多列的列表,常用于图片、文件等的网格化展示。然而,当GridView需要加载大量图片时,如果不妥善处理,很容易导致内存溢出(Out-Of-Memory,简称OOM)...
在Android开发中,GridView是一种常见的布局控件,用于展示大量数据,如图片、列表项等。然而,当GridView需要加载大量图片时,由于内存限制和性能问题,可能会出现明显的卡顿现象,严重影响用户体验。为了解决这个...
在Android开发中,图片处理是一项常见的任务,涉及到用户体验和应用性能。"android图片处理集合demo"是一个示例项目,集中展示了多种图片处理技术。虽然代码可能没有经过精心整理,但仍然能为开发者提供宝贵的参考。...
在Android开发中,异步批量下载图片并缓存是一个常见的需求,特别是在开发涉及大量图片展示的应用时,如社交应用、电商应用等。本教程将基于提供的Android例子源码,深入探讨如何实现这一功能。 首先,我们需要理解...
通过学习和使用"android图片裁剪demo",开发者不仅可以掌握图片裁剪的核心技术,还能了解到Android中处理大图、优化内存使用、提高用户体验等多个方面的最佳实践。这是一个宝贵的资源,可以帮助你在实际项目中快速...
这份"Android图片处理资料"很可能是关于Android平台上的图像处理技术的深入探讨,可能包括源码分析和相关工具的使用。虽然描述中没有提供具体信息,但我们可以从标题和标签中推测出一些可能涵盖的关键知识点。 1. *...