Fields
public Bitmap inBitmap If set, decode methods that take the Options object will attempt to reuse this bitmap when loading content.
public int inDensity The pixel density to use for the bitmap.
public boolean inDither If dither is true, the decoder will attempt to dither the decoded image.
public boolean inInputShareable This field works in conjuction with inPurgeable.
public boolean inJustDecodeBounds If set to true, the decoder will return null (no bitmap), but the out...
public boolean inMutable If set, decode methods will always return a mutable Bitmap instead of an immutable one.
public boolean inPreferQualityOverSpeed If inPreferQualityOverSpeed is set to true, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed.
public Bitmap.Config inPreferredConfig If this is non-null, the decoder will try to decode into this internal configuration.
public boolean inPurgeable If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged if the system needs to reclaim memory.
public int inSampleSize If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.
public boolean inScaled When this flag is set, if inDensity and inTargetDensity are not 0, the bitmap will be scaled to matchinTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas.
public int inScreenDensity The pixel density of the actual screen that is being used.
public int inTargetDensity The pixel density of the destination this bitmap will be drawn to.
public byte[] inTempStorage Temp storage to use for decoding.
public boolean mCancel Flag to indicate that cancel has been called on this object.
public int outHeight The resulting height of the bitmap, set independent of the state of inJustDecodeBounds.
public String outMimeType If known, this string is set to the mimetype of the decoded image.
public int outWidth The resulting width of the bitmap, set independent of the state of inJustDecodeBounds.

上表是BitmapFactory.Options的字段,现在详细介绍各个字段的作用:

1.inBitmap 这个一般用在Android3.0或者更高版本中,用来管理Bitmap的内存用的。如果设置了这个字段,那么解码图片的时候通过Option类去重用inBitmap这个已经存在的Bitmap的内存去加载新的Bitmap。这意味着,内存的重用从而改进性能,避免重新分配内存。但是运用inBitmap时必须确保一下三点:

  • 重用的Bitmap必须和即将解码的Bitmap的尺寸相同,且是JPEG或者PNG格式。(PS,另外还需要设置options.inMutable = true
  • BitmapFactory.Options.inPreferredConfig字段设置无效,因为会被重用的Bitmap的configuration所覆盖。
  • 一定要使用解码方法返回的Bitmap,因为重用可能会失败(例如:尺寸不匹配)。
以下是代码示例:

首先需要声明来保持Bitmap(已经用过的Bitmap)

HashSet<SoftReference<Bitmap>> mReusableBitmaps;private LruCache<String, BitmapDrawable> mMemoryCache;// 如果是3.0或者以上版本,注意这里必须使用软引用或者弱引用,从Android2.3(API 9)开始系统会更积极的回收被弱引用或者软引用所应用的///资源,在这里只是为了重用Bitmap内存来进一步提高性能,这里必须用软引用或者弱引用。至于图片的复用则用LruCache来实现(是强引用)。if (Utils.hasHoneycomb()) {    mReusableBitmaps = new HashSet<SoftReference<Bitmap>>();}
mMemoryCache = new LruCache<String, BitmapDrawable>(mCacheParams.memCacheSize) {    // 通知释放不需要的缓存,这个方法在每次add新的缓存时调用    @Override    protected void entryRemoved(boolean evicted, String key,            BitmapDrawable oldValue, BitmapDrawable newValue) {        if (RecyclingBitmapDrawable.class.isInstance(oldValue)) {            //自定义的BitmapDrawable,来降低它里面的引用计数            ((RecyclingBitmapDrawable) oldValue).setIsCached(false);        } else {            // 标准BitmapDrawable.在这里注意,是把已经不用的Bitmap保存起来,这个方法是内存缓存的图片的大小超过了指定的大小,需要抛弃不需要的图片,就是说能够被垃圾回收的Bitmap,不是缓存的Bitmap(在LruCache中的Bitmap)            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的内存空间:

public static Bitmap decodeSampledBitmapFromFile(String filename,        int reqWidth, int reqHeight, ImageCache cache) {    final BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    BitmapFactory.decodeFile(filename, options);    ...    // 如果运行在Android3.0或者更高的版本,就重用intBitmap的内存空间    if (Utils.hasHoneycomb()) {        addInBitmapOptions(options, cache);    }    ... //解码方法中的options的inBitmap的值有可能被设置过了,(就是重用Bitmap内存空间成功后会设置)    return BitmapFactory.decodeFile(filename, options);}
addInBitmapOptions()方法对options进行了设置,给options的inBitmap设置了在HasSet中保存的Bitmap,这样就重用了已经存在的Bitmap的内存空间。一下是方法的代码:

private static void addInBitmapOptions(BitmapFactory.Options options,        ImageCache cache) {    // inBitmap只有和inMutable一块使用才起作用,所以    options.inMutable = true;    if (cache != null) {        //  尝试寻找可重用内存空间的Bitmap        Bitmap inBitmap = cache.getBitmapFromReusableSet(options);        if (inBitmap != null) {            // 如果找到了,就给inBitmap设置值,这样就能用这个Bitmap的内存空间来生成新的Bitmap            options.inBitmap = inBitmap;        }    }}// 这个方法是在HasMap中寻找可重用内存空间的Bitmapprotected Bitmap getBitmapFromReusableSet(BitmapFactory.Options options) {        Bitmap bitmap = null;    if (mReusableBitmaps != null && !mReusableBitmaps.isEmpty()) {        final Iterator<SoftReference<Bitmap>> iterator                = mReusableBitmaps.iterator();        Bitmap item;//遍历HasMap中的Bitmap寻找尺寸和要生成的Bitmap尺寸相同的Bitmap        while (iterator.hasNext()) {            item = iterator.next().get();            if (null != item && item.isMutable()) {                // 检测是否可被重用,就是检测其尺寸(长和宽)是否和要新生成的Bitmap的尺寸(长和宽)相同,                if (canUseForInBitmap(item, options)) {                    bitmap = item;                    // 把这个能被重用内存空间的Bitmap从HashMap中删除,防止被两个以上重用导致的问题。                    iterator.remove();                    break;                }            } else {                // Remove from the set if the reference has been cleared.                iterator.remove();            }        }    }    return bitmap;}
canUseForInBitmap()这个方法就是检测options中目标Bitmap的尺寸(是原始尺寸通过和inSampleSize计算能够得到要显示的Bitmap的尺寸)和HashMap中Bitmap的尺寸(由于是以前生成过的Bitmap所以一定是缩放过的)是否相同。一下是代码实现:

private static boolean canUseForInBitmap(        Bitmap candidate, BitmapFactory.Options targetOptions) {    int width = targetOptions.outWidth / targetOptions.inSampleSize;    int height = targetOptions.outHeight / targetOptions.inSampleSize;    // 如果尺寸(长和宽)相同,就返回true    return candidate.getWidth() == width && candidate.getHeight() == height;}


PS:在这里补充一点,使用 BitmapFactory.decode* 方法解码生成图片,除了加载app自带的图片外,其他的都需要在非主线程中进行。

先写到这里,还用工作啊。。。。

更多相关文章

  1. Android:UI更新方法二:View.postInvalidate+Thread+Runnable
  2. Android(安卓)ViewPager动画切换
  3. 怎样实现android http-post方法
  4. android 入门 006(sqlite增删改查)
  5. android 7.0 user版本调试方法
  6. Android(安卓)SQLite数据库增删改查
  7. Android(安卓)实现事件监听的两个方法
  8. Android(安卓)ListView使用方法
  9. android EditText不弹出软键盘的方法

随机推荐

  1. 《Android开发艺术探索》第十章Android的
  2. Android doc 之应用程序基础
  3. Android 开发者在 Android Market 上兜售
  4. Android 零散知识点整理
  5. 【Android 开发】:数据存储之 SQLite 数据
  6. Windows上搭建Android开发环境详细教程
  7. 深入浅出 - Android系统移植与平台开发(十
  8. Android 开发者 for Flutter (1)Flutter和A
  9. 如何让TextView中的文字居中显示
  10. Android(安卓)Jetpack应用指南学习笔记6