使用Executors替代AsyncTask加载网络图片到ImageView时应用崩溃
问题根源与修复方案
核心问题
错误日志中的NetworkOnMainThreadException是崩溃的直接原因——你在主线程(按钮点击事件属于主线程)直接调用了mImageLoadTask.call(),而call()方法包含网络请求操作,Android禁止在主线程执行耗时网络任务,因此触发崩溃。
另外你的SendtoserverActivity中mContext未初始化,getContext()会返回null,后续加载错误占位图时也会引发异常。
修复步骤
1. 初始化Activity的Context
在Sendtoserver的onCreate方法中添加Context初始化代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sendtoserver); mContext = this; // 初始化Context // 其余原有代码... }
2. 用TaskRunner异步执行任务
不要直接调用call(),而是通过你实现的TaskRunner类将网络请求放到子线程执行,在回调中更新UI。修改按钮点击事件代码:
getfromurlbtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TaskRunner taskRunner = new TaskRunner(); taskRunner.executeAsync(mImageLoadTask, new TaskRunner.Callback<Bitmap>() { @Override public void onComplete(Bitmap result) { mImgfromurl.setImageBitmap(result); } }); } });
3. 优化资源释放(可选)
在ImageLoadTask的call()方法中添加资源关闭逻辑,避免内存泄漏:
@Override public Bitmap call() { HttpURLConnection connection = null; InputStream input = null; try { URL urlConnection = new URL(url); connection = (HttpURLConnection) urlConnection.openConnection(); connection.setDoInput(true); connection.connect(); input = connection.getInputStream(); return BitmapFactory.decodeStream(input); } catch (IOException exception) { return BitmapFactory.decodeResource(mContex.getResources(), R.drawable.ee); } finally { // 关闭资源 if (input != null) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } }
修复原理
TaskRunner的executeAsync方法通过线程池将Callable的执行逻辑放到子线程,避免主线程被耗时网络操作阻塞。- 任务执行完成后,通过
Handler切换回主线程更新UI,符合Android线程模型的要求(UI操作必须在主线程执行)。
内容的提问来源于stack exchange,提问作者eag-ehsan
相关产品推荐
相关产品推荐

