Drawable mutations

作者: Viking_Den | 来源:发表于2016-10-21 17:48 被阅读11次

Android's drawables are extremely useful to easily build applications. A Drawable is a pluggable drawing container that is usually associated with a View. For instance, a BitmapDrawable is used to display images, a ShapeDrawable to draw shapes and gradients, etc. You can even combine them to create complex renderings.

Drawables allow you to easily customize the rendering of the widgets without subclassing them. As a matter of fact, they are so convenient that most of the default Android apps and widgets are built using drawables; there are about 700 drawables used in the core Android framework. Because drawables are used so extensively throughout the system, Android optimizes them when they are loaded from resources. For instance, every time you create a Button, a new drawable is loaded from the framework resources (android.R.drawable.btn_default). This means all buttons across all the apps use a different drawable instance as their background. However, all these drawables share a common state, called the "constant state." The content of this state varies according to the type of drawable you are using, but it usually contains all the properties that can be defined by a resource. In the case of a button, the constant state contains a bitmap image. This way, all buttons across all applications share the same bitmap, which saves a lot of memory.

The following diagram shows what entities are created when you assign the same image resource as the background of two different views. As you can see, two drawables are created but they both share the same constant state, hence the same bitmap:

shared_states.png

This state sharing feature is great to avoid wasting memory but it can cause problems when you try to modify the properties of a drawable. Imagine an application with a list of books. Each book has a star next to its name, totally opaque when the user marks the book as a favorite, and translucent when the book is not a favorite. To achieve this effect, you would probably write the following code in your list adapter's getView() method:

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
}

Unfortunately, this piece of code yields a rather strange result, all the drawables have the same opacity:

all_drawables_changed.png

This result is explained by the constant state. Even though we are getting a new drawable instance for each list item, the constant state remains the same and, in the case of BitmapDrawable, the opacity is part of the constant state. Thus, changing the opacity of one drawable instance changes the opacity of all the other instances. Even worse, working around this issue was not easy with Android 1.0 and 1.1.

Android 1.5 offers a very way to solve this issue with a the new mutate() method. When you invoke this method on a drawable, the constant state of the drawable is duplicated to allow you to change any property without affecting other drawables. Note that bitmaps are still shared, even after mutating a drawable. The diagram below shows what happens when you invoke mutate() on a drawable:

mutated_states.png

Let's update our previous piece of code to make use of mutate():

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

For convenience, mutate() returns the drawable itself, which allows to chain method calls. It does not however create a new drawable instance. With this new piece of code, our application now behaves correctly:

correct_drawables.png

原文地址:
Drawable mutations
引申阅读:
Drawable 着色的后向兼容方案
Android SDK文档之Drawable Mutations
android 里面的 Drawable 和 ConstantState

相关文章

  • Drawable mutations

    Android's drawables are extremely useful to easily build ...

  • Android-Drawable mutations解析

    Drawable mutations 有没有遇到过这样一种情况,我们要加载同一资源到两个ImageView,但需要...

  • Vue 入门(二)—— 核心概念和简单示例

    一、store(仓库)包含 state 和 mutations,通过提交(commit) mutations 改变...

  • Mutations

    比较字符串 (蛤蟆可以吃队友,也可以吃对手) 如果数组第一个字符串元素包含了第二个字符串元素的所有字符,函数返回t...

  • mutations

    mutations 修改数据

  • Mutations

    比较字符串(蛤蟆可以吃队友,也可以吃对手)如果数组第一个字符串元素包含了第二个字符串元素的所有字符,函数返回tru...

  • mutations

    Vuex store状态的更新唯一方式:提交(commit) mutations Mutations主要包括两部分...

  • actions

    接上文mutations里的异步问题,在Vue Component 和 mutations之间增加actions环...

  • Drawable文件夹应用

    一、Drawable-hdpi、Drawable-mdpi、Drawable-ldpi、Drawable-xhdp...

  • 大型项目vuex构建

    在store文件夹下新建state.js,mutations.js,mutations-type.js,actio...

网友评论

    本文标题:Drawable mutations

    本文链接:https://www.haomeiwen.com/subject/dvdcuttx.html