Android根据Drawable图片名称字符串设置ImageView的问题
Android 根据图片名称设置ImageView到RecyclerView的解决方案
先解决getResources()废弃的问题
API 33之后getResources()被标记为废弃,替代方案是使用ContextCompat.getResources(Context),在Activity里可以这么写:
int resId = ContextCompat.getResources(this).getIdentifier(imageName, "drawable", getPackageName());
当然旧的getResources()目前仍能正常运行,只是官方不再推荐使用。
你的代码没效果的核心原因
getIdentifier()返回0就代表没找到对应资源,大概率是这几个问题:
- 文件名大小写不匹配:Android资源文件名仅支持小写字母、数字、下划线、连字符,数据库返回的名称如果有大写,必须转成小写后再查找:
int resId = ContextCompat.getResources(this).getIdentifier(imageName.toLowerCase(), "drawable", getPackageName()); - 资源目录放错:确保图片在
res/drawable目录下,而非mipmap(mipmap是专门存放应用图标的目录)。 - 混淆导致资源被移除:如果开启了ProGuard,它会删除未被硬编码引用的资源,需要在
proguard-rules.pro中添加规则保留drawable的ID类:-keep class **.R$drawable { *; } - 未判断resId是否为0:没找到资源时
resId会是0,此时setImageResource(0)不会显示任何内容,必须加判断兜底:if (resId != 0) { holder.imageSection.setImageResource(resId); } else { // 设置默认图避免空白 holder.imageSection.setImageResource(R.drawable.default_image); }
更高效的替代方案(推荐)
getIdentifier()基于反射实现,性能差且易出错,不如提前把图片名称和对应resId做成映射表:
- 在Application或Activity的
onCreate中初始化映射关系:
HashMap<String, Integer> drawableNameMap = new HashMap<>(); drawableNameMap.put("cat", R.drawable.cat); drawableNameMap.put("dog", R.drawable.dog); // 将所有需要用到的图片名称与ID一一对应添加
- 从数据库拿到名称后,直接从Map中取ID:
Integer resId = drawableNameMap.get(imageName.toLowerCase()); if (resId != null) { // 将resId传入RecyclerView适配器 }
- 适配器中直接设置图片:
holder.imageSection.setImageResource(resId);
为什么Android不能像iOS那样直接用名称?
Android的资源会被编译成唯一整数ID,系统还会根据设备分辨率、语言等自动匹配对应目录下的资源,并非直接按文件名读取,因此必须通过ID定位资源。而iOS的Bundle是直接按文件名查找资源,两者的资源管理机制存在本质差异。
内容的提问来源于stack exchange,提问作者Nicholas Farmer
相关产品推荐
相关产品推荐

