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

Android GridView 項目復用導致 CheckBox 狀態錯亂:getView 正確寫法

     編輯:程式設計綜合問答

現象

  • GridView 每項含 ImageView(內容)、TextView、CheckBox(打勾)。
  • 點擊第 1 項打勾,滑動到最後,最後一項莫名也打勾;第 1 項打勾消失。

根因

convertView 復用機制:getView(position, convertView, parent) 中,convertView 是被回收的舊 View。若**不根據數據模型重置所有子控件狀態**,舊狀態會「幽靈」般出現在新位置。

正確模式:ViewHolder + 數據驅動

public class MyAdapter extends BaseAdapter {
    private List data; // ItemData { int imgRes; String name; boolean checked; }

    static class ViewHolder {
        ImageView imgContent;
        TextView tvName;
        CheckBox cbCheck;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.grid_item, parent, false);
            holder = new ViewHolder();
            holder.imgContent = convertView.findViewById(R.id.img_content);
            holder.tvName = convertView.findViewById(R.id.tv_name);
            holder.cbCheck = convertView.findViewById(R.id.cb_check);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        // ★ 關鍵:每次必須根據數據模型**完全重置**所有可變狀態
        ItemData item = data.get(position);
        holder.imgContent.setImageResource(item.imgRes);
        holder.tvName.setText(item.name);
        holder.cbCheck.setChecked(item.checked); // 強制同步

        // ★ 點擊事件修改數據模型,不直接改 View
        holder.cbCheck.setOnClickListener(v -> {
            item.checked = !item.checked;
            notifyDataSetChanged(); // 或 notifyItemChanged(position) 若用 RecyclerView
        });

        return convertView;
    }
}

避坑清單

  1. 不要在 getView 里只處理「如果 checked 才 setChecked」 —— 必須有 else setChecked(false) 或直接 setChecked(item.checked)。
  2. 不要在 getView 里 new Listener 而不移除舊的 —— 用 setTag(position) 並在 Listener 里取 tag,或統一在 Activity 持有 OnItemClickListener。
  3. 大數據/頻繁更新改用 RecyclerView —— notifyItemChanged 粒度更細,自帶動畫,性能更好。

總結

**Adapter 只負責「數據 → View」的單向映射**。任何可交互狀態(勾選、輸入、展開)必須**持久化到數據模型**,getView 中**無條件同步**。這是 ListView/GridView/RecyclerView 正確使用的鐵律。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved