对抗out of memory之路

来源:互联网 发布:js字符串转数字相加 编辑:程序博客网 时间:2024/04/26 05:53

自从开始使用万恶的bitmap之后,各种的out of memory随之而来,永远的挥之不去,抗战经验总结于此。

1、使用out of memory 去度娘最多的都是告之你使用SoftReference来做缓存,然后用之,还是各种的崩啊,于是继续搜索找到一篇文章,是根据滑动将不在可视范围内的view中的bitmap recycle掉,第一次解决之,后来发现在使用listview和gridview时使用viewHolder就可解决此问题,因为view是重用的。


2、在写图片缓存时,V4包提供了LruCache的实现方式,原文地址:

      http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html。LruCache可以控制总缓存的大小,使用非常方便。

    mMemoryCache = new LruCache<String, Bitmap>(memCacheSize) {                        @Overrideprotected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {            Log.d(TAG, "======================图片被回收.key="+key);}/*  Measure item size in kilobytes rather than units which is more practical              for a bitmap cache            */             @Override            protected int sizeOf(String key, Bitmap bitmap) {                final int bitmapSize = getBitmapSize(bitmap) / 1024;                return bitmapSize == 0 ? 1 : bitmapSize;            }                                };

看看上面的代码就能大概了解下,这里注意在entryRemoved方法中不要去recycle bitmap,将会造成draw recycled bitmap exception。因为这里的回收只是清除出缓存,但是bitmap有可能还被view引用着。[这个有个疑问:这里的bitmap 在remove出去后内存就会降下来,但是并没有显性调用bitmap.recycle()方法,不知道有谁能解答下。]

已在官网找到说明:

除了缓存图片,你还可以做一些其他的事情来方便垃圾回收和再利用图片。推荐的策略取决
于设备的Android版本。
在Android 2.2和之前的Android版本中,当垃圾回收发生时,你的应用程序被停止。这将导致
程序滞后,可能会降低性能。Android 2.3增加了并发的垃圾回收,这意味着当一个图片的不
在被引用了,它所占用的内存会被立即回收。
在Android 2.3.3和较低的版本中,对于一个图片的像素数据被存储在本地内存中。而bitmap
对象本身被存储在Dalvik虚拟机的堆中。在本地内存中的像素数据不会以一种可预见的方式
被释放,可能会使得应用程序超过它的内存限制而导致崩溃。而到了Android 3.0,图片的像
素数据也被存储在Dalvik虚拟机的堆中。

在心得列子中使用了RecyclingImageView类来处理已remove的drawable,3.0以下的系统强制recycle效果更好。


3、所有的out of memory 都跟bitmap相关,因此在处理bitmap时一定要做好预处理。
final BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(path, options);// Calculate inSampleSizeoptions.inSampleSize = BitmapUtil.calculateInSampleSize(options,reqWidth, reqHeight);// Log.d(TAG, "从文件中读取:reqWidth,height=" + reqWidth + "," +// reqHeight + "原始大小:" + options.outWidth + "," + options.outHeight// + " ;inSampleSize=" + options.inSampleSize + ",path=" + path);// Decode bitmap with inSampleSize setoptions.inJustDecodeBounds = false;Bitmap b = BitmapFactory.decodeFile(path, options);

从网络或文件读取图片放置到imageView之前你需要计算得到图片相对手机的采样率,私家经验:做完采样率后如果你知道你的imageview需要多少大小的图片,先将图片裁切到所需大小,这样也可以提高效率并减少内存。比如你的图片时100*100的,而你的imageView是80*80的,采样率肯定是1,所以我们可以将图片缩小到80*80,再setbitmap,就减少了20*20*4的内存。


4、在退出界面时可将所有的iamgeview.setImageDrawable(null);我很疑惑为什么我需要掉这玩意,但在操蛋的galaxy S3上就是这样,你不调用,Y就是不回收内存。


5、现在的屏幕都到了1280P的境界了,弄个图片嗷嗷的吃内存啊,SO:给你的application加上android:largeHeap="true",这个会给你申请到更大的内存。


6、还是不行,有没有,特别在当年的主流机型上,什么G7,G14啦,还是各种崩,真想骂娘,怎么那么容易崩啊,祭出大招,android:process,你单进程限制我内存,我就来多进程,在一些与主进程无关的activity上可以使用此属性,然后你会想给吃内存的界面弄成另一个进程,但是它又需要去跟主进程通信,好吧,去学习下aidl吧,它是干这个的。


7、做完这么多好,是不是还会崩,你疯狂了没有,反正我已经被虐的死去活来了,你Y google这么牛,一个bitmap你不会好好回收啊。