• 2010-12-27

    [Code] Android备忘4 - BitmapDrawable.mutate() - [Code]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/sgzxy-logs/93307004.html

    2011.2.14

    对BitmapDrawable有了更深的认识后才发现有点错怪了Google那帮家伙,其实他们也早就意识到“原文”所提到的问题了,虽然做出补救是在SDK1.5才出现的,那就是BitmapDrawable.mutate()这个方法。

    详细可看这篇blog:http://android-developers.blogspot.com/2009/05/drawable-mutations.html

    原来Resources缓存的并不是个Drawable,而是Drawable中的State(比如BitmapDrawable的BitmapState)。是这个State起了一个share的作用,导致不同的Drawable产生了关联。而mutate就是重新创建一个State以避免共享。所以当要修改alpha时,只要mutate()后再修改即可。

    而如果要在SDK 1.5以下的版本回避这个问题,则可以采用下面原文所提的方法。

    然而,这个问题目前对于我来说已经很小儿科了,又出现了更头疼的问题,希望我能解决并分享解决方案。

     

    ===========================以下是原文=============================

    阅读之前要建立一个信念:Android就是一个给工程师折腾的东西(外观和用户体验也是),文档什么的只是浮云,更多的时候你只能去源码里折腾,否则你根本不知道Google那帮家伙到底写了啥逻辑。

    问题1:我用ImageView A做了个按钮,(用id引用drawable中的图片a),并做了个半透明效果(通过setAlpha),当用户Touch这个A时才不透明。现在我在另一处地方也需要用到图片a(不需要半透明行为),也是建立了一个新ImageView B并用id引用。然后你看看最终显示效果,会发现A和B保持着同样的外观,也就是要么A跟B一样不透明,要么B跟A一样半透明。

    解答:首先不说别的,单纯吐槽一下,两个独立的ImageView仅仅因为引用了同样一张图片,就产生了关联,设计API和背后的机制不是这么玩的啊……好吧,为了性能吧,有经验的立刻会想到,存在一个cache机制来确保每一个程序resource中的图片只被加载一次且只生成一个Drawable,并且A和B都引用了同一个Drawable。而setAlpha会改变背后的Drawable,于是A和B的外观会保持一样。

    那么这个cache是否能被关闭呢?看看API,提供了不少跟cache有关的方法哦,什么setDrawingCacheEnabled,什么setWillNotCacheDrawing,什么destroyDrawingCache,不过首先心一悬,这些方法都是来自View的,而且ImageView并未override;紧接着你进行试验,以上三个方法全部搭上,然后毫无效果。

    好吧,看源码吧,看这个cache到底是在哪进行的。看啊看,在ImageView源码的resolveUri函数中找到了答案,就是下面这句话:

    d = rsrc.getDrawable(mResource);

    这句话的意思是说,如果你是通过id引用drawable中的图片,那么会从rsrc(一个Resource对象)中来获取Drawable。于是明白了,是Resource进行了这个cache(哎早就该想到)。

    那怎么绕过这个cache呢?API不用指望了,Resource的这个cache行为粗看了下源码貌似是必须的(而且在大多数应用场景下是有利的)。所以应该对于需要修改图片透明度的ImageView,强制地创建新的Drawable。只讨论ImageView的Drawable为BitmapDrawable的情况,通过((BitmapDrawable)ImageView.getDrawable()).getBitmap()可以提取Bitmap,然后再new个新的BitmapDrawable并给ImageView重新setImageDrawable即可解决。

    当然更高效的做法,是对需要修改ImageView透明度的控件,实现一个你自己的Drawable缓存,只要这些ImageView不是同时出现在屏幕上即可。

    分享到:

    评论

  • 很久没来看你了……

    "文档什么的只是浮云,更多的时候你只能去源码里折腾,否则你根本不知道Google那帮家伙到底写了啥逻辑。
    "
    最近一星期做Heritrix和HTMLParser,深刻体会这句话……以前有良好文档从没体会这是多么幸福一件事……
    回复HYPER说:
    没错,当我用微软以外的技术时,才知道微软MSDN是多么牛逼。。
    真巧,我这段时间也是在做类似爬虫的东西……不过我是用C#自己写,正则表达式解析。本来是多线程,现在速度不够,要扩展成分布式,正在探索ing
    2011-02-06 15:58:15
  • 看你的备忘录真有喜感……