`
crazier9527
  • 浏览: 1010797 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于android中使用很多大图片的一些做法

 
阅读更多

 

最近在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

感谢:http://www.mangocd.com/

分享到:
评论

相关推荐

    Android有效解决加载大图片时内存溢出的问题

    Android 中加载大图片时内存溢出的...可以使用 BitmapFactory.Options、recycle() 方法、Java 中的内存优化技术、Android 中的内存优化技术、JNI 技术、避免使用大图片和缓存技术来减少内存的消耗,从而避免内存溢出。

    android ScrollView中 下拉放大图片

    这个功能在电商应用或者阅读类应用中很常见,用户下拉时图片会放大,松手后图片恢复原状,增加用户的互动体验。 首先,我们需要理解ScrollView的工作原理。ScrollView是LinearLayout的一个子类,它只允许一个直接的...

    Android App中使用Glide加载图片的教程

    很多情况下,我们使用图片加载库就是为了加载网络图片。网络操作是一个很复杂的东西。试想一下,如果没有图片加载库,我们就要手动去下载图片,缓存图片,最后再从文件里面读取bitmap并设置到Imageview里面。这还算好...

    Android图片浏览点击放大

    在Android开发中,图片浏览是常见的功能之一,尤其在社交应用、电商应用或者任何涉及到多媒体内容展示的应用中。本文将详细讲解如何实现Android图片浏览点击放大的功能,并结合提供的源代码进行深入解析。 首先,...

    android自定义控件多图片放大缩小显示

    3. **图片缩放**:在Android中,图片的缩放通常涉及到Matrix的使用。Matrix是一个二维变换矩阵,可以用来执行旋转、平移、缩放等操作。我们需要根据缩放比例更新Matrix,并调用ImageView的setImageMatrix()方法来...

    android框选图片中的一部分并截取

    在Android平台上,框选图片中的一部分并截取是一项常见的需求,比如在应用中实现自定义截图功能、编辑图片或者在图像处理中选择特定区域。这个功能涉及到多个Android SDK中的类和方法,包括图像处理、视图操作以及...

    android 图片放大缩小滑动

    综上所述,“GalleryDemo”示例涵盖了Android中图片放大、缩小和滑动的关键技术,包括手势识别、矩阵变换、视图状态管理等多个方面。理解并掌握这些知识点对于开发交互丰富的图像应用至关重要。

    Android中使用Gridview和ViewPager显示图片的优化处理

    本篇文章将详细探讨如何在Android应用中使用`GridView`和`ViewPager`来优化图片显示,避免内存溢出。 首先,我们需要理解为什么在Android上显示大量图片会引发OOM。当一个应用占用的内存超过系统分配的最大值时,就...

    Android图片加密、解密、切割(源码)

    本项目中使用的是一种名为DES(Data Encryption Standard)的加密算法。DES是一种对称加密算法,它使用相同的密钥进行加密和解密,具有速度快、安全性适中的特点。在Android中,可以使用Java Cryptography ...

    android 中ListView下载图片

    1. **异步加载库的选择**:Android社区中有多个成熟的库可以帮助我们实现图片异步加载,例如Universal Image Loader、Picasso、Glide等。这些库提供了方便的API,可以轻松地在ListView中加载网络图片或本地资源图片...

    最全的android图片加密

    在加密图片时,我们可以在原始数据中随机插入一些无关的字节,使得即使获取了加密后的数据,没有正确的“混入”规则也无法还原原图。这种方法可以进一步提高数据的安全性,防止针对AES等标准加密方式的攻击。 在...

    android gif图片循环显示

    添加后,记得同步项目,这样就可以在代码中使用`GIFView`了。 3. **使用GIFView显示GIF**:在布局XML文件中,添加`GIFView`组件: ```xml <com.daimajia.android.gif.GIFView android:id="@+id/gif_view" ...

    Android-Android仿微信的图片选择器带裁剪功能支持圆形和方形裁剪

    在Android应用开发中,创建一个类似微信的图片选择器是一个常见的需求,这涉及到用户界面设计、图片处理和文件管理等多个方面。"Android-Android仿微信的图片选择器带裁剪功能支持圆形和方形裁剪"这个项目就是这样一...

    android 动态添加图片

    在Android开发中,动态添加图片是一项常见的需求,例如在创建社交动态、编辑个人资料或实现图片选择器等场景。本文将深入探讨如何在Android应用中实现动态添加图片,并结合提供的`multiimagechooser-master`项目进行...

    android gridview 加载大量图片。无OOM

    在Android开发中,GridView是一种常见的布局控件,用于展示多行多列的列表,常用于图片、文件等的网格化展示。然而,当GridView需要加载大量图片时,如果不妥善处理,很容易导致内存溢出(Out-Of-Memory,简称OOM)...

    GridView加载大量图片卡的问题

    在Android开发中,GridView是一种常见的布局控件,用于展示大量数据,如图片、列表项等。然而,当GridView需要加载大量图片时,由于内存限制和性能问题,可能会出现明显的卡顿现象,严重影响用户体验。为了解决这个...

    android图片处理集合demo

    在Android开发中,图片处理是一项常见的任务,涉及到用户体验和应用性能。"android图片处理集合demo"是一个示例项目,集中展示了多种图片处理技术。虽然代码可能没有经过精心整理,但仍然能为开发者提供宝贵的参考。...

    Android例子源码异步批量下载图片并缓存

    在Android开发中,异步批量下载图片并缓存是一个常见的需求,特别是在开发涉及大量图片展示的应用时,如社交应用、电商应用等。本教程将基于提供的Android例子源码,深入探讨如何实现这一功能。 首先,我们需要理解...

    Android 利用CoordinatorLayout实现高仿抖音个人中心 下拉越界回弹 图片放大

    本示例中的“Android 利用CoordinatorLayout实现高仿抖音个人中心 下拉越界回弹 图片放大”就是一个很好的案例,它展示了如何通过 CoordinatorLayout 结合其他组件来构建类似抖音个人中心的下拉回弹以及图片放大效果...

    android图片裁剪demo

    通过学习和使用"android图片裁剪demo",开发者不仅可以掌握图片裁剪的核心技术,还能了解到Android中处理大图、优化内存使用、提高用户体验等多个方面的最佳实践。这是一个宝贵的资源,可以帮助你在实际项目中快速...

Global site tag (gtag.js) - Google Analytics