`
crazier9527
  • 浏览: 994860 次
  • 性别: 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 App中使用Glide加载图片的教程

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

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

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

    Android多图片上传

    Android多图片上传

    Android中多图片选择器PhotoPicker库的使用

    在Android项目的开发中,很多时候回用到选择相机,图片等功能这是我找的一个库,很好用上传上来供大家下载,希望能和大家交流

    Android加载/处理超大图片神器

    Android在加载或者处理超大巨型图片(x MB量级起步的图片)是一件非常需要小心谨慎的活儿,除了常规的OOM,其他需要处理的细节地方还很多,幸好开源社区github贡献了一套神器:SubsamplingScaleImageView...

    android点击查看大图,ViewPager实现左右滑动切换、缩放图片

    点击缩略图查看大图,支持滑动切换图片,缩放图片,封装成了一个工具类,基本两行代码实现上面需求。 代码很清晰,可以自已微调。

    轻量级的android原生图片选择拍照第三方库

    轻量级的android原生图片选择拍照第三方库 很容易使用,并且支持图片压缩多图片选择

    Android实现双击屏幕图片缩放效果.rar

    Android实现双击屏幕图片缩放效果,这个功能估计大家都见过不少吧,很多手机APP中就有,最直接的就是图库相册的预览功能里面,当显示图片缩略图的时候,双击屏幕,缩略图会按一定的比例放大显示图片,本源码所完成的...

    android客户端用socket不间断传输图片

    利用DataOutputStream...之间试过由OutpuStream.write(byte[])以及先将图片byte[]通过Base64加密转换为String再发送,效果都不好,可能是由于图片数据比文本数据还是相对大很多,发送一次还行,但是做不到不间断传输。

    android多图片选择Demo

    项目要求写一个多图片上传的功能,网上找了很多资源,都不太合适。就自己写了个

    Android实现imageView显示圆角图片、描边图片效果.rar

    Android实现imageView显示圆角图片、描边图片效果,具体效果请...这个例子主要是让大家熟悉imageView控件的用法技巧,除了可以实现圆形图片、圆角图片、为图片增加各种颜色大小的边框外,还有很多功能,敬请下载源码。

    android 图片异步下载

    android 图片异步下载,很实用。可以同时下载多张照片

    Android图片框架Glide-3.7.0(最新,很强大)

    该版本包括很多值得关注的新功能,如支持Gif 动画和视频剧照解码、智能的暂停和重新开始请求、支持缩略图等,具体新增功能如下如下: GIF 动画的解码 :通过调用Glide.with(context).load(“图片路径“)方法,GIF...

    android选择图片或拍照图片上传到服务器(包括上传参数)

    最近要搞一个项目,需要上传相册和拍照的图片,不负所望,终于完成了... 不过需要说明一下,其实网上很多教程拍照的图片,都是缩略图不是很清晰,所以需要在调用照相机的时候,事先生成一个地址,用于标识拍照的图片URI

    Android 小圆点滑屏滚动切换图片效果.rar

    Android左右滑屏滚动图片,很多APP在刚安装好初次运行,都会显示一个小圆点滑屏切换图片的效果,在QQ、微信或其它APP应用安装首次运行时,会有一个导航页特效,导航页下部显示小圆点,手机左右滑屏会切换导航页中的...

    Android4.0显示远程图片

    在网上查了很多,都是Android2.3版本的,在4.0及以上版本运行会出错,这次终于可以在Android4.0上正常使用了,特分享一下给新手

    android常用图片特效处理

    android常用图片特效处理,涵盖很多种类。比如灰度处理,颜色加深,自己看代码吧。有注释

    android图片对比

    花了两天做的一个图片对比Demo,现在很多android的都是直接流对比,自己写了一个是二维数组的对比,可以不管图片是否相同大小,还是其中一部分等等,缺少一个图片如果是旋转后的对比功能。对比图片是先把图片转成...

    android多线程异步下载图片

    多线程异步下载图片。 异步更新图片 里面注解很详细。

    Android中正确使用字体图标(iconfont)的方法

    可以减少项目和安装包的大小(特别你的项目中有很多图片icon时,效果将是M级)  3. 几乎可以忽略屏幕大小和分辨率,做到更好的适配  4. 使用简单  …… 缺点:   1. 只能是一些简单的icon,不能代替如...

Global site tag (gtag.js) - Google Analytics