android 全局背景色,Android-ColorDrawable引起的全局背景变化的探究

本文深入探讨了一个Android应用程序中因ColorDrawable缓存导致的全局背景色变化问题。问题表现为页面标题栏背景变透明,原因是快速滑动RecyclerView时,ColorDrawable的setAlpha方法修改了全局的ColorState。通过源码分析,发现ColorDrawable的ConstantState对象被多个Drawable共享,导致颜色状态变化影响全局。解决方法包括调用ColorDrawable的mutate()方法或使用新的ColorDrawable实例,以及避免通过DrawableProperties设置alpha。
摘要由CSDN通过智能技术生成

一、前言

在上个版本开发结束时,测试同学发现了一个偶现的 bug,页面是 RecyclerView 瀑布流显示 GIF 动画。

问题表现是页面标题栏白色背景变透明,进一步排查发现 App 中使用到该色值做背景的地方全部都被改了,而且改动无规律,即以色值 #ffffff 做背景的透明度都被改了。

比较容易复现的路径是,在该页面快速来回滑动列表。

这是一个 ColorDrawable 缓存导致的问题,老生常谈,今天就从源码的角度分析一下原因。

二、初步分析

通过问题表现可以知道肯定是有隐藏的操作改到背景的 alpha 值,进而导致全局改动。

2.1 在该页面中使用到 #ffffff 的地方主要有两个:

a. xml 设置控件背景 android:background=”@color/white_an”

b. 设置加载图片的占位图 ImageLoadParams.defaultholder = R.color.white_a

这两个色值都是定义在 values 中 #ffffff,都是很常规的操作。

查看系统方法 android.graphics.drawable.ColorDrawable#setAlpha

public void setAlpha(int alpha) {

alpha += alpha >> 7; // make it 0..256

final int baseAlpha = mColorState.mBaseColor >>> 24;

final int useAlpha = baseAlpha * alpha >> 8;

final int useColor = (mColorState.mBaseColor << 8 >>> 8) | (useAlpha << 24);

if (mColorState.mUseColor != useColor) {

mColorState.mUseColor = useColor;

invalidateSelf();

}

}

代码很简单,计算 alpha,颜色不一致时把最终计算得到的 useColor 赋值给 mColorState,并重绘自身。这个 mColorState 是什么呢?查看源码发现它是 ColorState 的实例,而 ColorState 又是继承自抽象类 ConstantState。

ConstatntState 的源码描述:

This abstract class is used by {@link Drawable}s to store shared constant state and data between Drawables.

{@link BitmapDrawable}s created from the same resource will for instance share a unique bitmap stored in their ConstantState.

也就是说,每个 Drawable 都共享一个唯一的 ConstantState 对象,这是为了共享 Drawable 的状态和数据,从同一个 res 中创建的 Drawable,它们会共享同一个 ConstantState 对象。

三、具体分析

我们看一下从 xml 加载 backgroud 的过程。

3.1 在 View 中解析 attr

public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {

this(context);

...

for (int i = 0; i < N; i++) {

int attr = a.getIndex(i);

switch (attr) {

case com.android.internal.R.styleable.View_background:

background = a.getDrawable(attr);

break;

...

}

}

...

}

3.2 继续跟到 android.content.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值