You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView滚动后ImageView位置错乱问题(使用Picasso)

解决RecyclerView+Picasso图片加载时视图错乱的问题

嘿,这个问题我之前做聊天界面的时候也踩过坑!核心问题就是RecyclerView的ViewHolder复用机制导致的视图状态残留,加上你在onBindViewHolder里没有完整重置所有视图的状态,才出现了滚动时图片位置错乱、文本消息被覆盖的情况。另外那个Logcat的错误日志和你的问题无关,先不用管它。

问题分析

你的代码里存在两个关键问题:

  1. 视图状态没有完全重置:当处理图片消息时,你只设置了对应ImageView和CardView可见,但在处理文本消息时,没有把图片相关的视图(imageMessageOut、cardViewOut等)设置为隐藏。当RecyclerView复用之前显示图片的ViewHolder来显示文本时,旧的图片视图会残留显示,导致错乱。
  2. Picasso加载请求未取消:ViewHolder被滚动出屏幕后,之前的图片加载请求可能还在后台运行,当请求完成时,图片会被加载到已经被复用的ViewHolder上,导致错误位置显示图片。

修复方案

修改你的onBindViewHolder方法,确保每次绑定都先重置所有视图状态,同时优化Picasso的加载逻辑:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val chat: Chat = mChatList[position]
    
    // 第一步:强制重置所有视图的可见性,彻底避免复用残留
    holder.textMessage?.visibility = View.GONE
    holder.imageMessageOut?.visibility = View.GONE
    holder.cardViewOut?.visibility = View.GONE
    holder.imageMessageIn?.visibility = View.GONE
    holder.cardViewIn?.visibility = View.GONE
    
    // 处理图片消息
    if (chat.getMessage() == "IMAGE" && chat.getUrl().isNotEmpty()) {
        if (chat.getSender() == currentUserID) {
            // 显示发送方图片视图
            holder.imageMessageOut?.visibility = View.VISIBLE
            holder.cardViewOut?.visibility = View.VISIBLE
            // 取消该ImageView上的旧请求,防止加载到错误位置
            Picasso.get().cancelRequest(holder.imageMessageOut)
            // 加载图片,可按需添加占位图提升体验
            Picasso.get().load(chat.getUrl())
                // .placeholder(R.drawable.default_image)
                .into(holder.imageMessageOut)
        } else {
            // 显示接收方图片视图
            holder.imageMessageIn?.visibility = View.VISIBLE
            holder.cardViewIn?.visibility = View.VISIBLE
            Picasso.get().cancelRequest(holder.imageMessageIn)
            Picasso.get().load(chat.getUrl())
                // .placeholder(R.drawable.default_image)
                .into(holder.imageMessageIn)
        }
    } 
    // 处理文本消息
    else {
        // 显示文本视图并设置内容
        holder.textMessage?.visibility = View.VISIBLE
        holder.textMessage?.text = chat.getMessage()
    }
}

额外说明

  • 关于Logcat的E/UIFirst: failed to open /proc/31416/stuck_info错误:这是系统层面的调试日志,和你的应用逻辑完全无关,不会影响功能,可以直接忽略。
  • 如果你的ViewHolder里还存在其他视图(比如时间、状态图标等),也要在开头的重置步骤里统一处理它们的状态,避免类似的复用问题。

内容的提问来源于stack exchange,提问作者Stackoverflower

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 10:52:51