最近在开发过程中遇到一个bug:我在一个recyclerview的onScrolled回调中改变另一个独立view的背景透明值,从而实现比较友好的交互效果。代码如下:
`mSearchViewLayout.getBackground().setAlpha(alpha);`
透明色的渐变功能没有问题,但是发现一个奇怪的现象,recyclerview的列表项的背景色变成了F8F8F8,而这个颜色我们代码中并不存在,debug发现,每次改变mSearchViewLayout的alpha值时,列表项的background alpha也会同步改变,然而这两个view并不想关,也没有事件联系。再次debug可以发现,两个view的背景都是纯白的ColorDrawable,并且ColorDrawable的mColorState类属性是同一个对象,原来是cache导致改变其中一个alpha为0时,另一个也同步更新,导致列表项显示的是rootview的默认颜色F8F8F8。查阅源码:
最终执行
可以发现有ConstantState的缓存Map,也就是复用了这个ConstantState,所以在一处改变,只要颜色相同的view也会随着改变。
说完来龙去脉,接下来说解决方法,google使用了缓存提升性能和效率当然也会考虑到这一点,ColorDrawable中有个mutate方法:
类似于克隆,让ColorDrawable重新持有一个新的ConstantState对象,并且不会重复创建。因为这个ConstantState对象不会被cache,新建的对象就不会对其他view产生影响。