您当前的位置: 首页 >  android

xiangzhihong8

暂无认证

  • 0浏览

    0关注

    1324博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

android bitmap的内存分配和优化

xiangzhihong8 发布时间:2016-04-25 10:55:51 ,浏览量:0

首先Bitmap在Android虚拟机中的内存分配,在Google的网站上给出了下面的一段话 

技术分享

大致的意思也就是说,在Android3.0之前,Bitmap的内存分配分为两部分,一部分是分配在Dalvik的VM堆中,而像素数据的内存是分配在Native堆中,而到了Android3.0之后,Bitmap的内存则已经全部分配在VM堆上,这两种分配方式的区别在于,Native堆的内存不受Dalvik虚拟机的管理,我们想要释放Bitmap的内存,必须手动调用Recycle方法,而到了Android 3.0之后的平台,我们就可以将Bitmap的内存完全放心的交给虚拟机管理了,我们只需要保证Bitmap对象遵守虚拟机的GC Root Tracing的回收规则即可。OK,基础知识科普到此。接下来分几个要点来谈谈如何优化Bitmap内存问题。

针对3.0版本的优化方案,请看以下代码,

private int mCacheRefCount = 0;//缓存引用计数器
private int mDisplayRefCount = 0;//显示引用计数器
...
// 当前Bitmap是否被显示在UI界面上
public void setIsDisplayed(boolean isDisplayed) {
    synchronized (this) {
        if (isDisplayed) {
            mDisplayRefCount++;
            mHasBeenDisplayed = true;
        } else {
            mDisplayRefCount--;
        }
    }

    checkState();
}

//标记是否被缓存
public void setIsCached(boolean isCached) {
    synchronized (this) {
        if (isCached) {
            mCacheRefCount++;
        } else {
            mCacheRefCount--;
        }
    }

    checkState();
}

//用于检测Bitmap是否已经被回收
private synchronized void checkState() {
    if (mCacheRefCount  reqWidth) {

            final int halfHeight = height / 2;
            final int halfWidth = width / 2;

            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }

            long totalPixels = width / inSampleSize * height / inSampleSize ;

            final long totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels > totalReqPixelsCap) {
                inSampleSize *= 2;
                totalPixels /= 2;
            }
        }
        return inSampleSize;
5.采用decodeFileDescriptor来编码图片,比直接使用decodeFile更省内存

查看BitmapFactory的源码,对比一下两者的实现,可以发现decodeFile()最终是以流的方式生成bitmap 

decodeFile源码:

[java]  view plain  copy
  1. public static Bitmap decodeFile(String pathName, Options opts) {  
  2.     Bitmap bm = null;  
  3.     InputStream stream = null;  
  4.     try {  
  5.         stream = new FileInputStream(pathName);  
  6.         bm = decodeStream(stream, null, opts);  
  7.     } catch (Exception e) {  
  8.         /*  do nothing. 
  9.             If the exception happened on open, bm will be null. 
  10.         */  
  11.     } finally {  
  12.         if (stream != null) {  
  13.             try {  
  14.                 stream.close();  
  15.             } catch (IOException e) {  
  16.                 // do nothing here  
  17.             }  
  18.         }  
  19.     }  
  20.     return bm;  
  21. }  

decodeFileDescriptor的源码,可以找到native本地方法decodeFileDescriptor,通过底层生成bitmap

decodeFileDescriptor源码:

[java]  view plain  copy
  1.    public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {  
  2.        if (nativeIsSeekable(fd)) {  
  3.            Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);  
  4.            if (bm == null && opts != null && opts.inBitmap != null) {  
  5.                throw new IllegalArgumentException("Problem decoding into existing bitmap");  
  6.            }  
  7.            return finishDecode(bm, outPadding, opts);  
  8.        } else {  
  9.            FileInputStream fis = new FileInputStream(fd);  
  10.            try {  
  11.                return decodeStream(fis, outPadding, opts);  
  12.            } finally {  
  13.                try {  
  14.                    fis.close();  
  15.                } catch (Throwable t) {/* ignore */}  
  16.            }  
  17.        }  
  18.    }  
  19.   
  20. private static native Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,Rect padding, Options opts);  

关注
打赏
1482932726
查看更多评论
立即登录/注册

微信扫码登录

0.0727s