Picasso加载URI至ImageView后,获取Drawable返回null的问题
解决Picasso加载后立即获取Drawable为null的问题
嘿,这个坑我刚踩过没多久!你现在的问题核心在于Picasso的图片加载是异步的——你调用Picasso.get().load(a).into(tempimg)之后,立刻去拿tempimg.getDrawable(),这时候图片还在后台下载/读取缓存呢,ImageView根本还没拿到Drawable,所以自然返回null啦。
为什么会这样?
Picasso为了不阻塞主线程,所有的图片加载操作都是在后台线程完成的,into()方法只是把加载任务提交出去,并不会等加载完成再返回。你写的代码是同步执行的,刚提交任务就去取结果,肯定拿不到嘛。
正确的解决方法
推荐用Picasso提供的Callback回调,等图片加载成功后再去获取Drawable,这样就不会有null的问题了:
val tempimg = ImageView(this) val imageUrl = pageURIFd + page Picasso.get().load(imageUrl).into(tempimg, object : Callback { override fun onSuccess() { // 这里图片已经稳稳加载完成了,放心拿Drawable val drawable = tempimg.drawable as BitmapDrawable bitmaps.add(drawable) // 如果后续要更新UI,这里本来就在主线程,直接操作就行 } override fun onError(e: Exception?) { // 别忘了处理加载失败的情况,比如打印错误或者给用户提示 e?.printStackTrace() // 也可以在这里加个默认占位图进去 } })
如果你更想直接拿到Bitmap(而不是通过ImageView中转),也可以用同步获取的方式,但一定要放在后台线程,不然会导致主线程阻塞ANR:
// 用Kotlin协程的例子,你也可以用Thread(不推荐AsyncTask) CoroutineScope(Dispatchers.IO).launch { try { val bitmap = Picasso.get().load(pageURIFd + page).get() val drawable = BitmapDrawable(resources, bitmap) // 切换回主线程更新集合(如果bitmaps是给UI用的) withContext(Dispatchers.Main) { bitmaps.add(drawable) } } catch (e: Exception) { e.printStackTrace() } }
小提醒
- 优先用第一种回调的方式,这是Picasso设计的标准用法,更符合Android的异步规范。
- 强制类型转换
as BitmapDrawable的时候最好加个安全判断,比如tempimg.drawable as? BitmapDrawable,避免类型不对导致崩溃。
内容的提问来源于stack exchange,提问作者Zim
相关产品推荐
相关产品推荐

