zoukankan      html  css  js  c++  java
  • Android 开发OOM解决方案

    OOM(Out Of Memory)在加载图片过多或者过大的情况下会发生OOM,可以查看APP最高可用内存:

      int maxMemory = (int) (Runtim.getRuntime().maxMemory()/1024);

    OOM问题如何解决?

    解决方案:

    1、使用强引用(StrongReference)、弱引用(WeakReference)、软引用(SoftReference)、虚引用(PhantomRefrence),在内存引用中做处理。

    2、在内存加载图片的时候,在内存中处理图片(边界压缩等)。

    3、动态回收内存。

    4、优化Dalvik的堆内存分配。

    5、自定义堆内存的大小。

    下面是对以上几点的详细描述:

    1、引用的处理。

      Heap中的对象有强可及、软可及、弱可及、虚可及和不可达对象。应用的强弱顺序是强、软、弱、虚。对于对象属于哪种可及对象,由它的最强引用决定。

      String abc = new String("abc"); // 建立强引用,内存中abc是强可及,不能释放内存。

      SoftReference<String> abcSoftRef = new SoftReference<String>(abc);// 建立软引用,仍然是强可及,不能释放内存。

      WeakReference<String> abcWeakRef = new WeakPeference<String>(abc);//建立弱引用,强可及,不能释放内存。

      abc = null;// 强引用取消,变成软可及

      abcSoftRef.clear();//软引用取消,变成弱可及

    总结:

      强引用:只能释放没有强引用指向的内存。http://i.cnblogs.com/EditPosts.aspx?postid=5543041

      弱引用:当Dalvik内存不足时,可以释放引用指向的内存。 

      软引用:无条件的执行Dalvik的指令。

      虚引用:和以上引用不一样,跟踪引用的释放过程。

    2、图片处理

      BitmapFactory提供了多个方法decodeFile()解析SD卡中的图片、decodeResource()解析资源文件图片、decodeStream()解析网络图片。

      2.1 单一图片压缩

      public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth,int repHeight){

        final int height = options.outHeight;

        final int width = options.outWidth;

        int inSampleSize = 1;

        if(height > reqHeight || width > reqWidth){

          final int heightRatio = Math.round((float) height/(float) reqHeight);

            final int widthRatio = Math.round((float) width/(float) reqWidth);

          inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

        }

        return inSampleSize;

      }

      public static Bitmap decodeSampleBitmapFromResource(Resource res, int resId,int reqWidth,int reqHeight){

        final BitmapFactory.Options options = new BitmapFactory.Options();

        options.inJustDecodeBounds = true;

        BitmapFactory.decodeResource(res, resId, options);

        options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);

        options.inJustDecodeBounds = false;

        return BitmapFactory.decodeResource(res,resId,options);

      }

      使用方式:

      imageView.setImageBitmap(decodeSampleBitmapFromResouce(getResource(),R.id.myimg,100,100));

      压缩流程:

      (1)、创建Options对象,将inJustDecodeBounds设置为true.

      (2)、解析图片,将属性值赋予options对象。

      (3)、计算压缩比例,将比例值赋予options的inSampleSize属性。

      (4)、将inJustDecodeBounds赋值false后,重新解析图片,返回Bitmap对象。

      2.2 批量图片处理

       处理单个照片的如上比较简单,但是一旦遇到批量图片处理,android为我们提供一个类LruCache,用于图片缓存(是一种内存缓存技术)。当缓存图片的数量到达预计设定的值的时候,近期使用比较少的图片会被回收掉。

      流程:

      private LruCache<String, Bitmap> mMemoryCache;

      private void initLurCache(){

        //1.设置缓存图片使用的内存大小,程序内存的八分之一。

        int cacheMemory = (int) (Runtime.getRuntime().maxMemory()/8);

        //2.初始化LruCache实例对象,重写sizeOf()、entryRemoved()方法。

        mMemoryCache = new LruCache<String, Bitmap>(cacheMemory){

                  //必须重写此方法,来测量Bitmap的大小
                  @Override
                  protected int sizeOf(String key, Bitmap value) {
                      return value.getRowBytes() * value.getHeight();
                  }
                  @Override
                  protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue) {
                      // TODO Auto-generated method stub
                      super.entryRemoved(evicted, key, oldValue, newValue);
                      removeBitmapCache(key);
                  }
              };

      }

      //3.分别实现清空缓存、添加图片到缓存、获取图片、从缓存移除图片

      public void addBitmapToMemoryCache(String key, Bitmap bitmap) {  
              if (getBitmapFromMemCache(key) == null && bitmap != null) {  
                  mMemoryCache.put(key, bitmap);  
             }  
         } 
         public Bitmap getBitmapFromMemCache(String key) {  
              return mMemoryCache.get(key);  
         }
         public void clearCache(){
              if (mMemoryCache != null && mMemoryCache.size() > 0) {
                  mMemoryCache.evictAll();
              }
         }
         public void removeBitmapCache(String key){
              if (key != null && mMemoryCache != null) {
                  Bitmap bitmap = mMemoryCache.remove(key);
                  if (bitmap!=null) {
                      bitmap.recycle();
                  }
              }
         }

    3、动态回收内存

      显示调用recycle()方法让GC回收内存。

      if(!abc.isRecycled()){

      abc.recycle();

      }

    4、优化Dalvik堆内存分配

      使用Dalvik.System.VMRuntime类提供的setTargetHeapUtilization()方法可以增强程序堆内存的处理效率。

      private final static float HEAP_UTILIZATION = 0.75f;

     //在onCreate()的时候调用

      Runtime.getRuntime().setTargetHeapUtilization(HEAP_UTILIZATION);

    5、自定义内存

      private final static int HEAP_SIZE  = 6*1024*1024;

      Runtime.getRuntime().setMinimumHeapSize(HEAP_SIZE);

  • 相关阅读:
    欧几里得算法&&扩展欧几里得算法
    POJ-1006 Biorhythms (生物节律)
    第3周实践项目7 删除链表元素最大值
    第3周实践项目1 顺序表的基本运算
    第三周项目4(2)-顺序表应用 将所有奇数移到所有偶数前面
    第3周实践项目5 -顺序表的应用 拆分单链表
    SDUT-2144 图结构练习——最小生成树
    SDUT-3362 数据结构实验之图论六:村村通公路
    Codeforces Round #616 (Div. 2)题解
    1.29 educational round 81
  • 原文地址:https://www.cnblogs.com/farmerkids/p/5543041.html
Copyright © 2011-2022 走看看