• 针对图片性能优化的总结


    由于android设备的RAM较小,且Java的GC机制不够智能,经常会出现Out of memory异常。 当然,除了上面的原因,也有可能就是因为写的程序有bug,产生内存溢出。在进行图片较多的软件处理时,很有可能会遇到OOM(out of memory)的异常。

    图片是一个非常消耗内存的资源,针对图片的处理需要进行特殊的处理。经过一段时间的调研,我总结出来几个注意事项。

    1.  尽量使用9png格式的图片
    2.  加载图片时,压缩图片后加载
    3.  尽快的手动标记回收图片资源
    4.  设置dalivk虚拟机的初始堆内存大小和GC效率(适用于不单单是图片的问题)
    5.  调用system.gc来执行垃圾回收(不赞成的方法)

    下面是对这几个内容的仔细分析:
    • 尽量使用9png格式的图片
        android系统为了提高图片的质量,提高android对各种屏幕的适应能力。系统推出了对.9.png格式图片的支持。这就就可以把一些图片在美工那里就做的非常小,之后还满足了产品对品质的要求。
    • 加载图片时,图片压缩后加载
        正常程序中加载图片调用函数:BitmapFactory.decodeFile(imageFile);
        为了在加载图片时可以对图片压缩后在加载,对前面的这段代码进行一下加工:
    1 BitmapFactory.Options opts =  new BitmapFactory.Options();
    2 opts.inJustDecodeBounds =  true ;
    3 Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

        设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

        查看Android源码,Android提供了一种动态计算的方法。

    01 public static int computeSampleSize(BitmapFactory.Options options,
    02          int minSideLength,  int maxNumOfPixels) {
    03      int initialSize = computeInitialSampleSize(options, minSideLength,
    04              maxNumOfPixels);
    05  
    06      int roundedSize;
    07      if (initialSize <=  8 ) {
    08          roundedSize =  1 ;
    09          while (roundedSize < initialSize) {
    10              roundedSize <<=  1 ;
    11          }
    12      }  else {
    13          roundedSize = (initialSize +  7 ) /  8 *  8 ;
    14      }
    15  
    16      return roundedSize;
    17 }
    18  
    19 private static int computeInitialSampleSize(BitmapFactory.Options options,
    20          int minSideLength,  int maxNumOfPixels) {
    21      double w = options.outWidth;
    22      double h = options.outHeight;
    23  
    24      int lowerBound = (maxNumOfPixels == - 1 ) ?  1 :
    25              ( int ) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
    26      int upperBound = (minSideLength == - 1 ) ?  128 :
    27              ( int ) Math.min(Math.floor(w / minSideLength),
    28              Math.floor(h / minSideLength));
    29  
    30      if (upperBound < lowerBound) {
    31          // return the larger one when there is no overlapping zone.
    32          return lowerBound;
    33      }
    34  
    35      if ((maxNumOfPixels == - 1 ) &&
    36              (minSideLength == - 1 )) {
    37          return 1 ;
    38      }  else if (minSideLength == - 1 ) {
    39          return lowerBound;
    40      }  else {
    41          return upperBound;
    42      }
    43 }  

         使用该算法,就可动态计算出图片的inSampleSize。然后去设置好inSampleSize后才去加载图片。

              //解决加载图片 内存溢出的问题 
    //Options 只保存图片尺寸大小,不保存图片到内存
    BitmapFactory.Options opts = new BitmapFactory.Options();
    //缩放的比例,缩放是很难按准备的比例进行缩放的,其值表明缩放的倍数,SDK中建议其值是2的指数值,值越大会导致图片不清晰
    opts.inSampleSize = 4;
    Bitmap bmp
    = null;
    bmp
    = BitmapFactory.decodeResource(getResources(), mImageIds[position],opts);

      

    • 尽快的手动标记回收图片资源
        在图片资源用完时,尽量手动的去标记一下这些已经用完的图片。帮助GC去识别不用的图片,并回收。
       
    if(bitmapObject.isRecycled()==false) //如果没有回收   
    bitmapObject.recycle();

      

    • 设置dalivk虚拟机的初始堆内存大小和GC效率(适用于不单单是图片的问题)
        对于Android平台来说,其托管层使用的Dalvik Java VM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。当然具体 原理我们可以参考开源工程,这里我们仅说下使用方法:   private final static float TARGET_HEAP_UTILIZATION = 0.75f; 在程序onCreate时就可以调用VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION); 即可。 
          对于一些Android项目,影响性能瓶颈的主要是Android自己内存管理机制问题,目前手机厂商对RAM都比较吝啬,对于软件的流畅性来说RAM对 性能的影响十分敏感,除了 优化Dalvik虚拟机的堆内存分配外,我们还可以强制定义自己软件的对内存大小,我们使用Dalvik提供的 dalvik.system.VMRuntime类来设置最小堆内存为例: 
    private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ; 
    VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
    //设置最小heap内存为6MB大小。当然对于内存吃紧来说还可以通过手动干涉GC去处理
    • 调用system.gc来执行垃圾回收(不赞成的方法)
        在以上功能均不能满足条件时,考虑使用该方法。
      
  • 相关阅读:
    GetEnumName 枚举名称 字符串
    拖拽文件
    小米手机Root 刷机
    微软语言 中文 英文 中英文
    MTP
    MD5加密算法全解析
    ORA-28000: the account is locked
    HTTP状态码
    HTTP 消息结构
    @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • 原文地址:https://www.cnblogs.com/xitang/p/2180057.html
Copyright © 2020-2023  润新知