Android 管理Bitmap内存 及 Bitmap.Config BitmapFactory.Options 说明
2015-06-09 17:36
477 查看
BitmapFactory.Options options = new BitmapFactory.Options();
/*
ARGB: alpha, red, green, blue
ALPHA_8 8位 1byte每像素1字节 按官方注释是说,只存alpha值,测试后发现,图片照样显示。。
ARGB_4444 16位 2bytes 已过时 像素2字节 (argb各范围为4位,即0~16)
ARGB_8888 32位 4bytes 每像素4字节(argb各范围0~255) 默认值
RGB_565 16位 不含Alpha 每像素2字节r:5bits(0~32), g:6bits(0~64), b:5bits(0~32)
测试发现内存的分配情况: ALPHA_8(23mb) ARGB_8888(23mb) RGB_565(13mb) ARGB_4444(15mb)
以上是反复销毁再创建的内存分配情况, 看出 前两者 较大, 后两者 较小
*/
options.inPreferredConfig = Config.RGB_565; //图片颜色配置
options.inSampleSize = 2; //宽高缩放比 这表示为原始的1/2
/*
如果设置为真,解码器将返回null(位图),但out..属性仍将被设置.
这时生成的bitmap为null, 调用options.outHeight
options.outWidth 能取到真实图片的宽高
*/
options.inJustDecodeBounds = true; //仅仅解码 bounds 即宽高,存在对应的out属性中
通过目标size,计算缩放比例:
String imageType = options.outMimeType; //图片的后缀名 比如jpeg png 这种
//decodeStream 比decodeResource 高效
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
> 在Android的Android 2.2(API 8级)及以下,当垃圾收集发生时,您的应用程序的线程都停止了。这会导致延迟,会降低性能。
在Android 2.3增加了并发垃圾回收,这意味着内存很快被回收后的位图不再引用。
> 在2.3及以下,the backing pixel data for a bitmap is stored in native memory.
存储在native内存中的bitmap,不会被释放,可能导致超出内存极限,而报oom。
在3.0及以上,bitmap的像素数据存储在Dalvik heap中的。
当调用该recycle()回收时,要确定该bitmap不再被使用。如果调用了recycle()后,又绘制该bitmap,将报异常:
“Canvas: trying to use a recycled bitmap”
下面的官方示例代码上,使用手动添加引用计数来处理,当mCacheRefCount、mDisplayRefCount都等0时才能recycle()
这意味着,位图被再利用,存储器不需要重新分配、解除分配,从而提高了性能。它存在的一定的限制,
在4.4以下时,只支持相同尺寸的bitmap;在4.4及以后,才支持不同尺寸的bitmap。
官方示例DisplayingBitmaps.zip
/*
ARGB: alpha, red, green, blue
ALPHA_8 8位 1byte每像素1字节 按官方注释是说,只存alpha值,测试后发现,图片照样显示。。
ARGB_4444 16位 2bytes 已过时 像素2字节 (argb各范围为4位,即0~16)
ARGB_8888 32位 4bytes 每像素4字节(argb各范围0~255) 默认值
RGB_565 16位 不含Alpha 每像素2字节r:5bits(0~32), g:6bits(0~64), b:5bits(0~32)
测试发现内存的分配情况: ALPHA_8(23mb) ARGB_8888(23mb) RGB_565(13mb) ARGB_4444(15mb)
以上是反复销毁再创建的内存分配情况, 看出 前两者 较大, 后两者 较小
*/
options.inPreferredConfig = Config.RGB_565; //图片颜色配置
options.inSampleSize = 2; //宽高缩放比 这表示为原始的1/2
/*
如果设置为真,解码器将返回null(位图),但out..属性仍将被设置.
这时生成的bitmap为null, 调用options.outHeight
options.outWidth 能取到真实图片的宽高
*/
options.inJustDecodeBounds = true; //仅仅解码 bounds 即宽高,存在对应的out属性中
通过目标size,计算缩放比例:
public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
String imageType = options.outMimeType; //图片的后缀名 比如jpeg png 这种
//decodeStream 比decodeResource 高效
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
管理Bitmap内存
官方地址:http://developer.android.com/training/displaying-bitmaps/manage-memory.html> 在Android的Android 2.2(API 8级)及以下,当垃圾收集发生时,您的应用程序的线程都停止了。这会导致延迟,会降低性能。
在Android 2.3增加了并发垃圾回收,这意味着内存很快被回收后的位图不再引用。
> 在2.3及以下,the backing pixel data for a bitmap is stored in native memory.
存储在native内存中的bitmap,不会被释放,可能导致超出内存极限,而报oom。
在3.0及以上,bitmap的像素数据存储在Dalvik heap中的。
在2.3及以下管理Bitmap内存
在2.3及以下,需要手动调用bitmap.recycle(),释放位图内存当调用该recycle()回收时,要确定该bitmap不再被使用。如果调用了recycle()后,又绘制该bitmap,将报异常:
“Canvas: trying to use a recycled bitmap”
下面的官方示例代码上,使用手动添加引用计数来处理,当mCacheRefCount、mDisplayRefCount都等0时才能recycle()
private int mCacheRefCount = 0; private int mDisplayRefCount = 0; ... // Notify the drawable that the displayed state has changed. // Keep a count to determine when the drawable is no longer displayed. public void setIsDisplayed(boolean isDisplayed) { synchronized (this) { if (isDisplayed) { mDisplayRefCount++; mHasBeenDisplayed = true; } else { mDisplayRefCount--; } } // Check to see if recycle() can be called. checkState(); } // Notify the drawable that the cache state has changed. // Keep a count to determine when the drawable is no longer being cached. public void setIsCached(boolean isCached) { synchronized (this) { if (isCached) { mCacheRefCount++; } else { mCacheRefCount--; } } // Check to see if recycle() can be called. checkState(); } private synchronized void checkState() { // If the drawable cache and display ref counts = 0, and this drawable // has been displayed, then recycle. if (mCacheRefCount <= 0 && mDisplayRefCount <= 0 && mHasBeenDisplayed && hasValidBitmap()) { getBitmap().recycle(); } } //验证bitmap是否能被回收 private synchronized boolean hasValidBitmap() { Bitmap bitmap = getBitmap(); return bitmap != null && !bitmap.isRecycled(); }
在3.0及以上管理内存
在3.0及以上添加了BitmapFactory.Options.inBitmap 标识,表示decode方法在加载内容将尝试加载它所指向的bitmap。这意味着,位图被再利用,存储器不需要重新分配、解除分配,从而提高了性能。它存在的一定的限制,
在4.4以下时,只支持相同尺寸的bitmap;在4.4及以后,才支持不同尺寸的bitmap。
保存位图便于以后使用
Set<SoftReference<Bitmap>> mReusableBitmaps; private LruCache<String, BitmapDrawable> mMemoryCache; // If you're running on Honeycomb or newer, create a // synchronized HashSet of references to reusable bitmaps. if (Utils.hasHoneycomb()) {//3.0及以上 mReusableBitmaps = Collections.synchronizedSet(new HashSet<SoftReference<Bitmap>>()); } mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) { // Notify the removed entry that is no longer being cached. @Override protected void entryRemoved(boolean evicted, String key, BitmapDrawable oldValue, BitmapDrawable newValue) { if (RecyclingBitmapDrawable.class.isInstance(oldValue)) { // The removed entry is a recycling drawable, so notify it // that it has been removed from the memory cache. ((RecyclingBitmapDrawable) oldValue).setIsCached(false); } else { // The removed entry is a standard BitmapDrawable. if (Utils.hasHoneycomb()) { // We're running on Honeycomb or later, so add the bitmap // to a SoftReference set for possible use with inBitmap later. mReusableBitmaps.add (new SoftReference<Bitmap>(oldValue.getBitmap())); } } } .... }
使用保存的Bitmap
….代码省略官方示例DisplayingBitmaps.zip
相关文章推荐
- Android自动登录界面
- 解析ANDROID ps命令执行后各项参数的含义
- android:ViewPager与FragmentPagerAdapter
- Android开发教程--第一个JNI程序
- Android下的数据存储与访问 --- 以文件的形式
- Android_Bitmap_图片的二次采样并生成缩略图
- [Android] 图片裁剪总结——调用系统裁剪
- Android布局中ScrollView与ListView的冲突的方法
- Unable to execute dex: Multiple dex files define 解决方法
- Android Studio 获取数字签名的方法
- 可望不可及的开源:Google是如何逐步牢牢控制开源系统Android的?(下)
- 如何调试分析Android中发生的tombstone
- Android 线性布局(LinearLayout)性能相关
- Android zxing二维码扫描 扫描框适应各种分辨率
- Android中自动跳转到系统设置界面
- android editText 软键盘enter键图标的设置
- android 反编译初级
- Android 4.1 systrace使用方法(一)
- android addr2line + objdump定位crash 问题
- java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.badlogic.androidgames.