ImageView设置图片时持续引用错误Drawable资源的问题求助
这种时不时抽风显示错误资源的情况真的挺闹心的,结合你用CardLayout+ListView的场景,咱们一步步来排查解决:
先从资源本身排查
检查资源命名与重复
先看看你的drawable资源里有没有同名文件?比如不同分辨率文件夹(drawable-hdpi、drawable-xhdpi这些)里,会不会有名字一样但内容完全不同的图片?Android会根据设备分辨率自动选资源,要是同名资源不一致,就很容易出现显示错乱。另外也别大意,有没有不小心把同名文件放错目录了?确认资源引用的正确性
不管是XML里设置android:src="@drawable/xxx",还是代码里用imageView.setImageResource(R.drawable.xxx),都要仔细核对引用的资源ID是不是你想要的。有没有可能变量混淆,比如把其他控件的资源ID错给了ImageView?
清理缓存要彻底
你已经做了Clean Project和重启AS,但试试更狠的:打开AS的File菜单,选Invalidate Caches...,然后勾选Invalidate and Restart。这个操作会清掉AS深层的缓存,很多顽固的资源缓存问题都能靠它解决,比单纯重启管用多了。
重点检查ListView的复用逻辑
因为你用了ListView,结合CardLayout的话,item复用导致的资源残留是重灾区!如果是自定义Adapter,在getView方法里,不管convertView是不是复用的,都必须给ImageView设置当前position对应的资源,绝对不能偷懒跳过。比如:
@Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder; if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.your_item_layout, parent, false); holder = new ViewHolder(); holder.itemImage = convertView.findViewById(R.id.item_image); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 这里必须强制设置当前项的资源,哪怕是复用的view也不能省! holder.itemImage.setImageResource(getItemImageRes(position)); return convertView; } static class ViewHolder { ImageView itemImage; }
要是你没做这一步,复用item的时候,ImageView就会显示上一个item的旧资源,看起来就像是“引用错误资源”了。
排查混淆问题
如果你开了ProGuard/R8混淆,看看是不是资源ID被混淆错了。可以在混淆规则里加上保护资源的配置:
-keepresources drawable/**,layout/**,menu/** -keep public class * extends android.view.View { public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); public void set*(...); }
也可以先关掉混淆重新编译,看看问题会不会消失,以此判断是不是混淆搞的鬼。
手动清理构建目录
要是上面都没用,就手动删除项目根目录下的build文件夹,还有app模块里的build文件夹,然后执行Rebuild Project。有时候构建目录里的旧资源没被清干净,编译时就会引用错误的文件。
最后建议
如果还是解决不了,把Tab1 Fragment里完整的ImageView设置逻辑,还有ListView的Adapter代码、布局文件贴出来,这样能更精准地定位问题。毕竟有时候细节才是关键~
内容的提问来源于stack exchange,提问作者kumail

