如何用Runnable替代AsyncTask实现ImageView加载Firebase存储图片
用Thread/Runnable替代AsyncTask加载图片到ImageView
因为Android不允许在子线程中更新UI组件,所以你需要在子线程完成Bitmap解码后,把设置ImageView的操作切换回主线程执行。下面是两种可行的实现方式:
方式一:使用Activity的runOnUiThread()
直接在子线程获取到Bitmap后,通过*runOnUiThread()*把UI操作抛回主线程:
new Thread(new Runnable() { @Override public void run() { URL url = null; Bitmap bmp = null; try { url = new URL("你的Firebase Storage图片URL"); bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream()); } catch (MalformedURLException e) { Log.d("Error", e.toString()); } catch (IOException e) { Log.d("Error", e.toString()); } // 保存Bitmap引用,避免在runOnUiThread中捕获变量问题 final Bitmap finalBmp = bmp; // 切换到主线程更新UI runOnUiThread(new Runnable() { @Override public void run() { if (finalBmp != null) { imageMessage.setImageBitmap(finalBmp); } } }); } }).start();
方式二:使用Handler传递消息
创建一个绑定到主线程的Handler,在子线程中发送包含Bitmap的消息,Handler在主线程处理消息并更新UI:
// 在Activity/Fragment中定义主线程Handler private Handler mainHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { if (msg.what == 1) { Bitmap bmp = (Bitmap) msg.obj; if (bmp != null) { imageMessage.setImageBitmap(bmp); } } } }; // 启动子线程加载图片 new Thread(new Runnable() { @Override public void run() { URL url = null; Bitmap bmp = null; try { url = new URL("你的Firebase Storage图片URL"); bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream()); } catch (MalformedURLException e) { Log.d("Error", e.toString()); } catch (IOException e) { Log.d("Error", e.toString()); } // 发送消息到主线程Handler Message message = mainHandler.obtainMessage(1, bmp); mainHandler.sendMessage(message); } }).start();
注意事项
- 别忘了在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" /> - 直接用
BitmapFactory.decodeStream可能会导致OOM,建议根据ImageView的尺寸对Bitmap进行缩放处理 - 实际开发中更推荐使用Glide、Picasso等图片加载库,它们已经封装了异步加载、缓存、内存优化等逻辑,Firebase Storage也有官方的集成支持,可以更简洁地实现图片加载
内容的提问来源于stack exchange,提问作者Jeff Li
相关产品推荐
相关产品推荐

