Android RecyclerView展示图片列表时添加数据触发主线程网络异常崩溃
崩溃原因定位
从你贴的崩溃日志可以100%确定问题根源:
- 报错触发点在
SearchDogAdapter.onBindViewHolder方法内,也就是你手写的拉取远程图片流的代码:BitmapFactory.decodeStream(url.openConnection().getInputStream()) onBindViewHolder是RecyclerView的主线程回调,所有绑定逻辑都运行在应用主线程上。Android自API 11开始就强制禁止在主线程执行任何网络I/O操作,只要触发就会直接抛出NetworkOnMainThreadException终止应用。- 你传空列表时不崩溃的逻辑也能对应上:空列表时
getItemCount()返回0,RecyclerView不会执行任何Item的绑定流程,自然走不到网络请求的代码段。只要列表填充了数据,RecyclerView开始绑定Item视图,就会立刻触发主线程网络请求,造成崩溃。
修复方案
绝对不要在主线程、更不要在Adapter的绑定回调里手写网络流拉取Bitmap的逻辑,这类耗时操作必须全部放到后台线程执行。
可落地的修改思路:
- 直接使用成熟的图片加载框架替换手写的图片加载逻辑,框架已经帮你封装了后台线程拉取、图片压缩、内存/磁盘缓存、列表滚动时的无效加载取消、Bitmap复用等全部细节,一行代码就能完成图片加载,完全规避主线程网络问题,同时解决后续快速滚动时的图片错位、内存溢出隐患。
- 如果你不想引入新依赖,可以复用项目里已经接入的Volley组件,使用其自带的
ImageLoader类加载远程图片,所有网络请求都会在后台线程调度,不会触发主线程网络限制。 - 严禁通过开启
StrictMode的主线程网络权限来绕过这个崩溃,这种写法会直接阻塞主线程,导致应用卡顿、ANR,属于严重违规的开发实践。
额外提两个开发隐患:
- 当前Adapter中强引用MainActivity实例,在Fragment页面销毁时容易引发内存泄漏,加载图片时优先使用Context的ApplicationContext,不要强绑定Activity实例。
- 手写的Bitmap加载逻辑没有做尺寸压缩处理,加载大图时很容易触发OOM崩溃。
内容的提问来源于stack exchange,提问作者Jiren
相关产品推荐
相关产品推荐

