结论:android中从同一个资源文件中加载出来的drawable会共享状态,若是有加载出来多个drawable的实例对象,当改变了其中一个的状态时,其余drawable的状态也会相应改变。android
实例:在修改一个view,或者它的background,即时是新建立的view对象,若是它是从同一个xml中加载出来的(包括矢量图、shape等),在代码中动态修改的它颜色,会影响到其余从该xml加载出的view。这是由于它的mGradientState是被复用的。ide
下面两个图,是从同一个xml中加载的view对象(在recyclerView的两个item中),在动态改变了第二个view的background颜色后,若是第一个view所在的item从新bind,新建立出的view,也表现出和原来第二个view一样的背景颜色。修改颜色的方法以下:this
private fun changeBackgroundColor(@ColorInt argb: Int?) { argb?.let { if (mRootView?.background is GradientDrawable) { val grad: GradientDrawable = mRootView?.background as GradientDrawable grad.setColor(argb) } } }
能够看到,这个两个view的background对象,确实是两个不一样的对象,可是他们的mGradientState,是同一个GradientState
对象,这里发生了复用。spa
而GradientState.setColor
方法,修改的正是mGradientState中保存的颜色值。该方法以下,能够看到方法注释里也提醒了咱们会影响全部从同一resource中加载的drawable:code
因此,在动态修改drawable的颜色(或者GradientState中其余属性)时,须要将改该drawable设置为mutate状态,即调用mutate()
方法,该方法会为drawable建立新的mGradientState(Drawable的各派生类实现有所不一样)。GradientDrawable.mutate()方法以下:xml
@Override public Drawable mutate() { if (!mMutated && super.mutate() == this) { mGradientState = new GradientState(mGradientState, null); updateLocalState(null); mMutated = true; } return this; }
因此须要将上述修改背景颜色的方法,修改以下:对象
private fun changeBackgroundColor(@ColorInt argb: Int?) { argb?.let { if (mRootView?.background is GradientDrawable) { val grad: GradientDrawable = (mRootView?.background as GradientDrawable).mutate() as GradientDrawable grad.setColor(argb) } } }