在xml中设置ImageView源时,Android会自动使用inJustDecodeBounds吗?

在xml中设置ImageView源时,Android会自动使用inJustDecodeBounds吗?,android,bitmap,android-bitmap,Android,Bitmap,Android Bitmap,我知道,如果我以编程方式加载图像并将其设置为ImageView中的源,最好的做法是首先使用inJustDecodeBounds计算图像的大小,计算出需要的缩放比例,然后使用该缩放比例进行解码: BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.drawable.m

我知道,如果我以编程方式加载图像并将其设置为ImageView中的源,最好的做法是首先使用
inJustDecodeBounds
计算图像的大小,计算出需要的缩放比例,然后使用该缩放比例进行解码:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.drawable.my_drawable, options);

float srcHeight = options.outHeight;
float srcWidth = options.outWidth;

int inSampleSize = ...; // compute

options = new BitmapFactory.Options();
options.inSampleSize = inSampleSize;

Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.my_drawable, options);

myImageview.setImageBitmap(myBitmap);
现在,如果我想在xml中设置它,并且我只在
/drawables
中提供一个基本的drawable(在
/drawables hdpi
中没有其他资产,等等)


我知道Android会对生成的位图进行某种缩放,以确保其适合,但它会像我自己解码位图一样高效地进行缩放吗?还是将整个位图加载到内存中,然后进行缩放


换句话说,当Android由自己的设备重新采样图像时,当我只提供一个基本的
/drawable
时,它是否能有效地这样做?

如果你确定你想要的大小,你自己缩放位图将节省内存,因为Android不会这样做,至少不是你期望的方式(请参见底部的编辑和注释)

我认为您还需要做一些其他考虑。当您自己解码位图时,您的目标是一个大小,可能是
ImageView
的大小(因此在计算了
ImageView
的大小之后)。膨胀xml时,该大小未知。如果解码
位图后
图像视图的大小发生变化,会发生什么情况?您会重新缩放它吗?在这种情况下,解码更大的
位图,然后只缩放图形不是更有效吗

要想知道android是否像你一样缩放位图,一个方法很简单,试着在xml中设置一个可笑的大图像作为src,看看会发生什么(剧透警报,它会爆炸)

public static Drawable createFromResourceStream(Resources res, TypedValue value,
        InputStream is, String srcName, BitmapFactory.Options opts) {
    if (is == null) {
        return null;
    }

    /*  ugh. The decodeStream contract is that we have already allocated
        the pad rect, but if the bitmap does not had a ninepatch chunk,
        then the pad will be ignored. If we could change this to lazily
        alloc/assign the rect, we could avoid the GC churn of making new
        Rects only to drop them on the floor.
    */
    Rect pad = new Rect();

    // Special stuff for compatibility mode: if the target density is not
    // the same as the display density, but the resource -is- the same as
    // the display density, then don't scale it down to the target density.
    // This allows us to load the system's density-correct resources into
    // an application in compatibility mode, without scaling those down
    // to the compatibility density only to have them scaled back up when
    // drawn to the screen.
    if (opts == null) opts = new BitmapFactory.Options();
    opts.inScreenDensity = Drawable.resolveDensity(res, 0);
    Bitmap  bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
    if (bm != null) {
        byte[] np = bm.getNinePatchChunk();
        if (np == null || !NinePatch.isNinePatchChunk(np)) {
            np = null;
            pad = null;
        }

        final Rect opticalInsets = new Rect();
        bm.getOpticalInsets(opticalInsets);
        return drawableFromBitmap(res, bm, np, pad, opticalInsets, srcName);
    }
    return null;
}
另外,在
draw(Canvas Canvas)
method of
BitmapDrawable
中,使用以下行完成绘制:

canvas.drawBitmap(bitmap, null, mDstRect, paint);
看起来像是使用了
位图
,是目标
Rect
进行缩放

编辑


今天我还意外地发现了另一件有趣的事情,我将一幅图像放在可绘制文件夹(未指定密度)中,并使用
BitmapFactory.decodeSourceStream(res、value、is、pad、opts)检索了一幅位图
,与上面的一样。我得到的位图比drawable文件夹中的图像大得多,我认为如果密度未指定,它将采用mdpi,甚至会对位图进行上采样以获得更高的目标密度。

使用巨大的png进行测试的好主意。谢谢,准备看到它爆炸:)今天我还发现了一些新的东西,我把它放在回答栏里,尝试了一个巨大的图像,然后:砰:。此外,在这个类似的问题中,您所说的未指定密度的图像大小也得到了暗示:。如果你改为使用
drawable nodpi
会发生什么?嗯,好问题,根据你告诉android不要缩放图像的方式!我想我不会再使用资产文件夹了
canvas.drawBitmap(bitmap, null, mDstRect, paint);