当在XML布局中声明了2个ImageView时,内存中会有2个drawable的副本吗?

4

当我有一个如下的xml布局:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/my_image" />

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/my_image" />

那么在内存中与可绘制图案相关联的位图实例是2个还是仅有1个?


如果您想在程序中动态更改drawable的着色颜色,那么从另一个屏幕加载相同的drawable资源 - drawable的着色将与您在程序中定义的一样,因此我猜它被缓存了。 - Pavel Poley
谢谢,我认为这就是@tynn答案所指的。 - Marian Paździoch
3个回答

3
Resources中加载可绘制对象时,这些对象将被缓存到DrawableCache中,而DrawableCache是一个ThemedResourceCache
在注释中,ResourcesImpl指出:
// First, check whether we have a cached version of this drawable
// that was inflated against the specified theme. Skip the cache if
// we're currently preloading or we're not using the cache.

你能提供一下那个的源链接吗? - Marian Paździoch
1
@MarianPaździoch 我添加了谷歌源链接。 - tynn
你知道这个缓存是指Abhisek Mallick在下面回答的内容吗? - Marian Paździoch
我认为缓存主要处理状态。Drawable是可变结构,因此缓存整个对象可能更具问题性。 - tynn

1

好问题!!!

我已经查看了源代码,看起来每个ImageView都会创建新的位图实例。这其中有一个繁琐的过程...

ImageView使用Drawable

Drawable使用ImageDecoder

ImageDecoder使用BitmapFactory

BitmapFactory使用native C++ code进行图像解码。(查看第157行及以下)

简单地浏览代码告诉我,即使使用相同的图像,它也会为每个ImageView创建新的位图Drawable实例。我没有找到任何相关于这种优化的逻辑。

更新

是的,在位图加载的情况下发生了优化。Abhisek Mallick是完全正确的。即使不查看代码,也很容易检查。创建一个带有ImageView的RecyclerView。将相同的位图加载到这些ImageView中。然后尝试更改项目数。在更改时查看Profiler->Memory。内存分配不会改变。


看看Abhisek Mallick和tynn的答案 - 我认为你的不正确。 - Marian Paździoch

0
你可以在这里找到答案:
例如,每次创建按钮时,都会从框架资源(android.R.drawable.btn_default)中加载新的可绘制对象。这意味着所有应用程序中的所有按钮都使用不同的可绘制实例作为其背景。但是,所有这些可绘制对象共享一个称为“常量状态”的公共状态。
来源: https://android-developers.googleblog.com/2009/05/drawable-mutations.html?m=1

1
这是一篇非常有用的博客文章! - Marian Paździoch
@MarianPaździoch,如果您在上下文中发现它有用,请点赞该答案。 - Abhisek Mallick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接