Android Studio使用Retrofit+Gson时ImageView无法加载URL图片求助
问题排查与修复方案
- 核心问题:子线程直接操作UI。安卓系统禁止非主线程更新View组件,你在自定义的工作线程中直接调用
setImageBitmap方法设置图片,属于非法操作,不会生效甚至会触发崩溃。 - 复用错位问题:RecyclerView的item会被复用,每次
onBindViewHolder都开启新线程加载图片,没有绑定当前item的位置,滑动时会出现图片串位的问题。 - 资源泄漏问题:加载图片的
InputStream使用后未主动关闭,会造成内存泄漏;未做图片缓存,滑动时重复请求网络,性能差。 - 潜在解析问题:如果Photo类的字段名和接口返回的字段不完全匹配,Gson会解析出空值,导致图片链接无效。
修复步骤
1. 替换线程逻辑,切主线程更新UI
把onBindViewHolder中的线程逻辑替换为AsyncTask实现,自动切主线程更新,同时增加位置校验避免错位:
@Override public void onBindViewHolder(RecyclerViewHolder holder, @SuppressLint("RecyclerView") int position) { holder.title.setText(photos.get(position).title); holder.albumid.setText(photos.get(position).albumId); holder.regid.setText(photos.get(position).id); // 先设置占位图,避免显示复用的旧图片,换成你自己项目里的占位资源即可 holder.circleImageView.setImageResource(R.drawable.ic_placeholder); holder.imageView.setImageResource(R.drawable.ic_placeholder); String thumbUrl = photos.get(position).thumbnailUrl; String imgUrl = photos.get(position).url; new AsyncTask<Void, Void, Bitmap[]>() { @Override protected Bitmap[] doInBackground(Void... voids) { Bitmap thumbBitmap = getBitmapFromURL(thumbUrl); Bitmap imgBitmap = getBitmapFromURL(imgUrl); return new Bitmap[]{thumbBitmap, imgBitmap}; } @Override protected void onPostExecute(Bitmap[] bitmaps) { // 校验当前holder的位置是否匹配,避免滑动时图片错位 if (holder.getAdapterPosition() != position) return; if (bitmaps[0] != null) { holder.circleImageView.setImageBitmap(bitmaps[0]); } if (bitmaps[1] != null) { holder.imageView.setImageBitmap(bitmaps[1]); } } }.execute(); }
2. 优化图片加载方法,关闭输入流
修改getBitmapFromURL方法,主动关闭资源避免内存泄漏:
public static Bitmap getBitmapFromURL(String src) { HttpURLConnection connection = null; InputStream input = null; try { Log.e("src",src); URL url = new URL(src); connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.connect(); input = connection.getInputStream(); return BitmapFactory.decodeStream(input); } catch (IOException e) { e.printStackTrace(); Log.e("Exception",e.getMessage()); return null; } finally { // 主动关闭资源 if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } }
3. 其他检查项
- 检查Photo类的字段名是否和接口返回一致,比如
thumbnailUrl、url字段大小写、拼写完全匹配,否则Gson会解析为空。 - 如果你用的是http的图片链接,Android 9及以上默认禁止明文传输,需要在
AndroidManifest.xml的application标签中增加android:usesCleartextTraffic="true"配置,或者把图片链接换成https。 - ApiInterface中的
@GET("/photos")可以去掉开头的斜杠,改为@GET("photos"),避免路径拼接出错。
内容的提问来源于stack exchange,提问作者Jessica Almany
相关产品推荐
相关产品推荐

