如何检查Android Drawable资源是否存在夜间模式变体?
如何检查Android Drawable资源是否存在夜间模式变体?
嘿,这个场景我太熟悉了——用Glide加载资源时碰到主题切换的缓存问题,还要被迫存两份其实没必要的Drawable,确实挺糟心的。其实咱们可以先判断目标Drawable有没有对应的夜间模式变体,再决定要不要给Glide加区分明暗的签名,这样就能避免缓存冗余啦。
下面给你两种实用的检查方法,结合你的Glide场景来用:
方法一:通过资源标识符查找夜间变体
Android的夜间模式资源一般会放在带night限定符的目录(比如drawable-night),我们可以利用Resources.getIdentifier()来定位对应的资源是否存在:
fun hasNightModeDrawable(context: Context, drawableResId: Int): Boolean { val resources = context.resources // 获取原资源的名称、类型和包名 val resName = resources.getResourceEntryName(drawableResId) val resType = resources.getResourceTypeName(drawableResId) val resPackage = resources.getResourcePackageName(drawableResId) // 构造夜间模式的配置,用来查找对应变体 val nightConfig = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES } // 尝试获取夜间模式下的资源ID val nightResId = resources.getIdentifier(resName, resType, resPackage, nightConfig) // 返回是否找到有效资源(非0即存在) return nightResId != 0 }
这个方法的核心是通过指定夜间模式的配置,去查找同名同类型的资源,如果能拿到有效的ID,就说明这个Drawable有对应的夜间变体。
方法二:通过临时Context验证(备选)
如果担心getIdentifier的性能(毕竟它是反射式查找),也可以创建一个临时的Context,切换到夜间模式后尝试获取资源,对比原资源是否有差异:
fun hasNightModeDrawable(context: Context, drawableResId: Int): Boolean { val originalDrawable = ContextCompat.getDrawable(context, drawableResId) ?: return false // 创建夜间模式的Context val nightContext = context.createConfigurationContext( Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES } ) val nightDrawable = ContextCompat.getDrawable(nightContext, drawableResId) ?: return false // 如果两个Drawable不是同一个实例(说明有不同变体),返回true return originalDrawable !== nightDrawable }
不过这个方法会实际加载Drawable,可能比第一种方法开销大一点,适合不频繁调用的场景。
结合Glide场景使用
拿到判断结果后,就可以优化你的签名逻辑了:
val drawableRes = R.drawable.your_target_drawable // 判断当前是否处于深色模式 val isInDarkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES // 只有当存在夜间变体时,才用区分明暗的签名 val signature = if (hasNightModeDrawable(context, drawableRes)) { ObjectKey(drawableRes.toString() + if (isInDarkMode) "_dark" else "_light") } else { ObjectKey(drawableRes.toString()) } // 之后正常用这个签名加载资源即可 Glide.with(context) .load(drawableRes) .signature(signature) .into(imageView)
小提醒
如果你的项目里需要频繁检查资源,建议把检查结果缓存起来(比如用HashMap<Int, Boolean>),避免重复执行查找逻辑,提升性能。
备注:内容来源于stack exchange,提问作者ubuntudroid
相关产品推荐
相关产品推荐

