使用Picasso将Firebase图片绑定到RecyclerView失败,请问写法是否有误?
问题排查与修正方案
你代码里存在以下几处明确的问题,是导致图片加载失败的核心原因:
- ImageView类型错误:你代码中
imgViewUser声明的是View?类型,Picasso的into()方法仅支持接收ImageView实例,类型不匹配会直接导致加载失败。 - 图片地址的类型与空安全问题:
- Picasso的
load()方法更推荐直接传入Firebase返回的String类型图片URL,你使用URI类型作为参数容易出现解析异常 - 没有对
model.images?.get(0)做空判断,当图片列表为空时会触发空指针异常
- Picasso的
- 协议适配问题:如果你的Firebase返回的是
gs://开头的Storage存储地址,Picasso本身不支持直接加载gs协议地址,需要先调用Firebase Storage的getDownloadUrl()方法拿到https格式的可下载地址再传入Picasso。 - 权限检查:确认你在
AndroidManifest.xml中已经添加了网络权限:<uses-permission android:name="android.permission.INTERNET" />
修正后的核心代码
override fun onBindViewHolder(holder: UserViewHolder, position: Int, model: Game) { val tvGameName: TextView = holder.itemView.findViewById(R.id.tvHeading) // 修正1:直接声明为ImageView类型 val imgViewUser: ImageView? = holder.itemView.findViewById(R.id.titleImage) tvGameName.text = model.documentId // 修正2:做空判断+转为String类型URL val imgUrl = model.images?.get(0)?.toString() if (!imgUrl.isNullOrEmpty() && imgViewUser != null) { // 可选:添加placeholder和error占位图提升体验 Picasso.get() .load(imgUrl) .fit() .centerCrop() .placeholder(R.drawable.ic_placeholder) // 替换为你自己的占位图资源 .error(R.drawable.ic_error) // 加载失败显示的占位图 .into(imgViewUser) } // 调试完成后请删除这段Toast,onBindViewHolder执行频繁会重复弹出 // Toast.makeText(applicationContext, "image is $imgUrl", Toast.LENGTH_LONG).show() }
针对gs协议地址的额外处理
如果你拿到的地址是gs://开头的Firebase Storage路径,需要先获取可下载的https链接再加载:
val imgGsPath = model.images?.get(0)?.toString() if (!imgGsPath.isNullOrEmpty() && imgViewUser != null) { val storageRef = FirebaseStorage.getInstance().getReferenceFromUrl(imgGsPath) storageRef.downloadUrl.addOnSuccessListener { uri -> Picasso.get() .load(uri.toString()) .fit() .centerCrop() .into(imgViewUser) }.addOnFailureListener { imgViewUser.setImageResource(R.drawable.ic_error) } }
内容的提问来源于stack exchange,提问作者Eric Low
相关产品推荐
相关产品推荐

