Drawable Mutations(Android Drawable 深入分析)

这篇文章帮助你更好了解Android's drawables对象,这篇文章描述现象你可以不知道,但是当你遇到了该问题也许一两天也不一定找到解决方案。

Android's drawables对编写程序是非常有用的。A Drawable通常是一个与view相关的插件后的画图容器。例如。一个aBitmapDrawable是用来显示图片的,a ShapeDrawable 是用来画图和渐变的等等。你甚至可以通过它还创建负责的渲染。

Drawables允许你不需要继承就可以很容易的定制widgets渲染。事实是,Android的应用程序和widgets 是使用该drawables对象的,在android的核心框架中大约有700个drawables被使用。正式以为他是如此广泛的被使用,Android对它进行了优化。例如,每一次你创建一个按钮时,一个新的drawable就会被装载。这就意味着应用程序中所有的使用不同drawablesd对象实现不同背景的按钮,所有的drawables对象公用一个公用的状态,我们成“constant state”,这个状态的内如根据你使用的不同drawables对象而不同,但是它通常包括一个资源所有的属性。以按钮为例,常态包括一个位图。如此一所有按钮就可以共享一张位图。这将会节省很多的资源。

下面的图介绍了你设置一张图给两个不同View作为背景的创建过程。正如你所看到的那样,两个drawables被创建,但是共享公共的部分也就是同一张位图。



 

这种状态分享特点极大避免了浪费内存,但是当你试图去修改drawable的属性时它会导致一些问题。假设是关于书的的列表的程序,书名之后会当你标注为喜欢的时候显示为不透明的而标注不喜欢的时候完全透明星星。为了达到这样的效果,你也许会在你的adapter个getView实现下面的方法:

 

Book book = ...;
TextView listItem = ...;

listItem.setText(book.getTitle());

Drawable star = context.getResources().getDrawable(R.drawable.star);
if (book.isFavorite()) {
  star.setAlpha(255); // opaque
} else {
  star.setAlpha(70); // translucent
}

不幸的是,上面的那段代码会有一个很奇怪的结果,所有的drawables对象都会有相同的透明值。

这种结果能够用上面的“常态”来解释。因为我们从一个list item中获取一个drawable对象时,constant state是一样的,对BitmapDrawable来说,透明值就是一个常态,因此,改变一个drawable对象实例的透明值来说,会改变所有其他对象的透明值,更糟糕是,这种问题在1.1和1.0的是不好解决的。

在1.5或者更好的设备上通过mutate()方法是很容易解决上述问题。当你对一个drawable对象调用这个方法时,drawable对象就会被复制而不会印象其他对象。记住bitmap对象依旧是被重用的,即使是实用mutate(),下面这幅图说明调用mutate()对象之后情况:

让我更新一下我们的代码:

Drawable star = context.getResources().getDrawable(R.drawable.star);
if (book.isFavorite()) {
  star.mutate().setAlpha(255); // opaque
} else {
  star. mutate().setAlpha(70); // translucent
}

为了方便mutate()是返回drawable对象自己,这就允许我们采用链的方法调用,他不会产生新的对象,通过上面的代码片段,我的程序行为变得正常。

 

posted on 2011-06-13 23:34  lbeing  阅读(5282)  评论(0编辑  收藏  举报

导航