You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android硬编码drawable偶现加载错误 AAB分发版本随机显示异常图片

异常诱因

  • 资源收缩工具误删动态引用资源:项目开启shrinkResources资源收缩优化时,工具仅会静态扫描代码中直接显式引用的R.drawable.xxx资源,你通过字符串UID映射资源ID的引用方式无法被识别,映射表中用到的drawable会被标记为未使用资源被移除。运行时传入无效资源ID时,系统会随机加载其他可用drawable代替,导致显示错乱。
  • 侧装不完整拆分APK:应用通过AAB分发时,Google Play会根据设备的屏幕密度、ABI、语言等配置拆分生成多个独立APK,用户如果从非官方渠道侧装了不完整的拆分APK包,或者多个拆分APK版本不匹配,会导致资源ID和实际资源的对应关系错乱,出现随机图片。

解决方案

  • 配置资源保留规则,避免误删:在res/xml/keep.xml中添加规则,显式保留映射表中用到的所有drawable资源,避免被资源收缩工具移除:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@drawable/find_care_*,@drawable/primary_care" />
  • 改为运行时通过资源名获取ID:不要直接硬编码映射R类的int ID,改为映射资源的字符串名称,运行时通过资源名动态获取ID,从根源上避免资源ID变动带来的错乱问题。参考修改逻辑:
// CommonSearchModel伴生对象修改
companion object {
    val mapping = mapOf<String, String>(
        "{some ID}" to "find_care_primary_care",
        "..." to "find_care_obgyn",
        "..." to "find_care_dermatology",
        "..." to "find_care_pediatrics",
        "..." to "find_care_urgent_care",
        "..." to "find_care_psychiatry"
    )
    @JvmStatic
    fun getIllustration(context: Context, uid: String): Int {
        val resName = mapping[uid] ?: "primary_care"
        // 动态根据资源名获取ID
        val resId = context.resources.getIdentifier(resName, "drawable", context.packageName)
        // 兜底默认资源
        return resId.takeIf { it != 0 } ?: R.drawable.primary_care
    }
}

同时调整列表绑定逻辑,在绑定时再调用方法获取资源ID:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    with (data[position]) {
        // ...
        val imgRes = CommonSearchModel.getIllustration(holder.itemView.context, uid)
        holder.itemView.illustration.setImageResource(imgRes)
        // ...
    }
}
  • 添加安装完整性检测:添加应用安装完整性校验逻辑,识别到是侧装的不完整AAB拆分包时,提示用户前往Google Play下载官方安装包。

内容的提问来源于stack exchange,提问作者Orbit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 11:27:03