由于不赞成使用无参数BitmapDrawable
构造函数,我们必须为该构造函数提供资源id。
BitmapDrawable bitmapDrawable = new BitmapDrawable(res, bmap);
其中res
一般为getResources()
。
为什么构造函数需要它?如果我们使用通用图像缓存,我们如何定义该值?
构造函数为什么需要它?
来自BitmapDrawable(Resources res, Bitmap bitmap)
:的文档
从位图创建可绘制对象,根据资源的显示指标设置初始目标密度。
因此,这是使用显示度量设置初始目标密度所必需的,并且DisplayMetrics
将从作为参数提供给BitmapDrawable
的Resources
中提取。
如果使用通用图像缓存,我们如何定义该值?
对不起,我不能理解这个问题。你能换个说法吗?
如果我自己已经缩放了位图,为什么BitmapDrawable需要资源?
BitmapDrawable
怎么知道你已经缩放了Bitmap
?通常,如果您正在创建BitmapDrawable
,则不应该自行对其进行缩放,这就是为什么API是这样设计的。
将位图转换为Drawable时,避免缩放的唯一方法似乎是使用不推荐使用的构造函数?
虽然这听起来很糟糕,但您可以看到转换框架中的类是如何使用该构造函数的,例如ChangeBounds
、Crossfade
。
我挖掘了一些源代码,在Bitmap
类中找到了这段代码:
static public int scaleFromDensity(int size, int sdensity, int tdensity) {
if (sdensity == DENSITY_NONE || tdensity == DENSITY_NONE || sdensity == tdensity) {
return size;
}
// Scale by tdensity / sdensity, rounding up.
return ((size * tdensity) + (sdensity >> 1)) / sdensity;
}
这在以下链中被调用:
* BitmapDrawable#constructor
* BitmapDrawable#updateLocalState()
* BitmapDrawable#computeBitmapSize()
* Bitmap#getScaledWidth()
* scaleFromDensity(getWidth(), mDensity, targetDensity)
如果您将Bitmap
的密度明确设置为DENSITY_NONE
,该怎么办?然后CCD_ 16检查将评估为CCD_ 17,并且将不执行缩放。
Bitmap bitmap = ...
bitmap.setDensity(Bitmap.DENSITY_NONE);
没有测试,只是根据来源做出假设。
在此构造函数中,需要getResources()"根据资源的显示度量设置初始目标密度"。我是这样理解的——你获取显示指标,其中包含关于大小、密度、字体缩放的信息,并将这些信息传递给构造函数。如果您在res/
文件夹中有不同大小的图像——在适当的子文件夹中,如drawable-ldpi
、drawable-hdpi
——您可能会得到不同的信息。
要在图像缓存中使用它,您需要向它传递一个Context,然后像这样调用:Context ctx; ctx.getResources();
希望能有所帮助。
关于已弃用的构造函数和新构造函数
BitmapDrawable(Resources res) /* deprecated constructor */
BitmapDrawable(android.content.res.Resources, android.graphics.Bitmap) /* new constructor they introduced to replace above deprecated constructor */
不推荐使用的构造函数创建了一个空的drawable,而不处理密度。但是,新的构造函数从位图创建drawable,根据资源的显示度量设置初始目标密度。使用新的构造函数可以为您提供Bitmap(最终类)所能提供的所有功能。https://developer.android.com/reference/android/graphics/Bitmap.html#pubmethods
如果不通过构造函数传递位图变量,会发生什么从参数传递变量时,不需要在传递的位置创建新的位图变量。您创建了另一个变量,它只是引用位图的(静态引用)。由于位图是大尺寸文件,当您传递引用时,您节省了在ImageView中加载位图所需的大量空间和处理能力。所以它可以帮助你避免OutOfMemory Exception
。
例如,
public void passA(String); /* method signature*/
String s = "dfsfsdf";
passA(s); /* method calling */
另一面:
public void passA(String newVar) {
/* newVar simply points (references) to the memory of "dfsfsdf". */
/* passing references */ /* for Bitmap creating new copy is expensive
operations */
/*Note: Java does manipulate objects by reference, and all object variables are references */
}
他们传递Bitmap变量(android.graphics.Bitmap)的另一个想法是因为Bitmap是Parcelable(如果实现Parcelable)。Parcelable对象可以包含在Bundle中。捆绑包是IPCS(进程间通信)和通过各种Android组件进行通信的核心。
关于常规图像缓存您可以从位图中设置所有必要的密度和其他内容,位图通过新的构造函数传递了一个变量。然后,您可以在Least Recently Used (Lru)
缓存中创建一个HashMap,在其中定义字符串key
以指出配置的Bitmap variable
。例如,LruCache。现在,在处理器的最近最少缓存中,您已经配置了位图。这样可以节省大量的处理能力。
https://developer.android.com/reference/android/util/LruCache.html
希望,我的回答能帮助你!