首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android ListView 滑動出現數據陰影/重疊的原因排查與解決

     編輯:程式設計綜合問答

問題描述

ListView 在滑動加載數據時,偶爾出現項目重疊、殘留「陰影」或顯示錯亂的現象,必須重啟應用才能恢復。這通常發生在數據量大、項目佈局複雜或異步加載圖片的場景。

常見原因

  1. View 復用機制導致的狀態殘留:getView 中未正確重置 View 狀態(如圖片未清空、文字未更新、標籤 Tag 未清理),導致舊數據顯示在新項目上。
  2. 異步圖片加載未取消舊任務:項目滑出屏幕後,關聯的圖片加載任務完成時回調更新了已被復用的 View,造成圖片錯位。
  3. 佈局高度不穩定:項目佈局使用 wrap_content 且內容動態變化,導致 ListView 測量錯誤,滑動時位置計算偏差。
  4. 硬件加速繪製異常:部分舊機型開啟硬件加速時,ListView 滑動繪製存在 Bug。

解決方案

1. 規範 getView 寫法(ViewHolder 模式)

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = inflater.inflate(R.layout.item_layout, parent, false);
        holder = new ViewHolder(convertView);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    // 關鍵:每次綁定前重置狀態
    holder.imageView.setImageResource(R.drawable.placeholder); // 設置佔位圖
    holder.textView.setText(""); // 清空文字

    // 綁定新數據
    ItemData data = getItem(position);
    holder.textView.setText(data.title);
    imageLoader.load(data.url, holder.imageView); // 圖片加載庫自動處理取消/復用

    return convertView;
}

static class ViewHolder {
    TextView textView;
    ImageView imageView;
    ViewHolder(View view) {
        textView = view.findViewById(R.id.tv_title);
        imageView = view.findViewById(R.id.iv_icon);
    }
}

2. 使用成熟的圖片加載庫

推薦 Glide、Picasso 或 Coil。它們內部自動處理:

  • 請求取消(View 復用時自動取消舊請求)
  • 內存緩存與磁盤緩存
  • 生命週期集成(Activity/Fragment 銷毀自動清理)

3. 關閉硬件加速(針對性嘗試)

<!-- 在 AndroidManifest.xml 中 Application 或 Activity 標籤 -->
<application android:hardwareAccelerated="false" ...>
<!-- 或單獨關閉 ListView -->
listView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

4. 避免佈局嵌套過深,固定項目高度或使用 RecyclerView 替代

RecyclerView 強制要求 ViewHolder 模式,提供 DiffUtil 高效更新,默認項目動畫更流暢,是 ListView 的現代替代品。

排查清單

  • [ ] getView 是否每次都重置所有可見控件狀態?
  • [ ] 圖片加載是否使用成熟庫並綁定 View 生命週期?
  • [ ] 項目佈局根節點高度是否為 match_parent 或固定 dp?
  • [ ] 是否在主線程做耗時操作導致幀率下降?
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved