开发者

BitmapFactory.Options.inTempStorage field

I have a custom offline map implemented by drawing Bitmap tiles on Canvas. I'm trying to eliminate object creations to reduce GC runs and therefore make the map scrolling smoother. I see in Allocation Tracker that BitmapFactory.decodeFile(...) always creates byte[16400] object. I thought that setting inTempStorage field of BitmapFactory.Options would change that:

byte[] buffer = new byte[16*1024];
// ...
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
options.inTempStorage = buffer;
Bitmap 开发者_StackOverflow社区bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);

But even with this code I still see decodeFile creating the byte[] array. So what's the problem?


In short, the problem is that when you use BitmapFactory.decodeFile(String, Options) then Android will allocate a 16 kB BufferedInputStream, independently of options.inTempStorage.

To be more elaborate: BitmapFactory.decodeFile(String, Options) is a wrapper around BitmapFactory.decodeStream(InputStream, Rect, Options) that uses a FileInputStream. In the implementation of BitmapFactory.decodeStream(InputStream, Rect, Options), there is this code:

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
    // ...

    // we need mark/reset to work properly
    if (!is.markSupported()) {
        is = new BufferedInputStream(is, 16 * 1024);
    }

    // ...
}

Since FileInputStream's markSupported() returns false, that means that independently of options.inTempStorage, a BufferedInputStream with a 16 kB buffer will be created for you if you use BitmapFactory.decodeFile(String, Options).

To avoid this 16 kB allocation, you could try to use BitmapFactory.decodeStream(InputStream, Rect, Options) directly with an InputStream for which markSupported() returns true.

I can think of two alternatives that could be worth looking into:

  1. Use your own BufferedInputStream with a smaller buffer
  2. Use AssetManager.AssetInputStream as returned by AssetManager.open(...) (see my answer here on how to use it). Its markSupported() returns true.

The first alternative might not help much, you'll still have a byte[] array allocated, but at least it is under your control. The second option might turn out to be the most fruitful, if your circumstances allows you to use this approach.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜