ListView 数据在滚动时被清除

ListView Data got cleared on scrolling

我正在开发一个显示 listViewcheckBoxes 的应用程序。 当我滚动 listView 时,CheckBoxes 的值被清除。

下面是我的代码

适配器class:

public class Conference_listViewAdapter extends BaseAdapter {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
    ViewHolder holder;
    int pos;

    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) {
        data = list;
        this.id_list = id_list;     
        this.context = context;
    }


    @Override
    public int getCount() {
        return data.size();
    }


    @Override
    public Object getItem(int position) {
        return data.get(position).getName();
    }

    @Override
    public long getItemId(int position) {
        return Long.valueOf(id_list.get(position));
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        View view = null;

        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

            holder.favorite.setTag(data.get(position));
        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }


        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
                Model element = (Model) holder.favorite.getTag();
                element.setSelected(buttonView.isChecked());     
                //notifyDataSetChanged();
            }
        });


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }

    class ViewHolder {
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
    }


}

数据模型class

public class Model {

    private String name;
    private boolean selected;

    public Model(String name) {
        this.name = name;
        selected = false;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }

} 

不知道哪里做错了

改变这个..

  @Override
public Object getItem(int position) {
    return position;
}

到..

  @Override
public Object getItem(int position) {
    return data.get(position);
}

更新:

试试这个..

public View getView(final int position, View convertView, ViewGroup parent) {

    View view = null;

    if (convertView == null) {
        LayoutInflater inflator = context.getLayoutInflater();
        view = inflator.inflate(R.layout.people_list_item1, null);
        holder = new ViewHolder();
        holder.title = (TextView) view.findViewById(R.id.tv_name);
        holder.image = (ImageView) view.findViewById(R.id.avtaar);
        holder.favorite = (CheckBox) view.findViewById(R.id.fav);
        holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
               //do what you want..   
            }
        });

        view.setTag(holder);
    } else {
       holder = (ViewHolder) view.getTag();
    }

    holder.favorite.setChecked(data.get(position).isSelected());
    holder.title.setText(data.get(position).getName());



    try {
        holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
    } catch (Exception e) {
        e.printStackTrace();
    }

    return view;
}

在类似的情况下,比如带有复选框、单选按钮、计数框等的列表视图,我通常按如下方式操作 1)保留一个大小类似于列表视图(行数)的数组列表 2) 这个 array/arraylist 将在适配器 class 的构造函数中初始化,所有位置都为零 3) 在声明复选框并将其标签设置为 position

之后在 getView() 中
public class Conference_listViewAdapter extends BaseAdapter {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();
     ArrayList<String> myarray=new java.util.ArrayList<String>();   
    ViewHolder holder;
    int pos;


    public Conference_listViewAdapter(Activity context,List<Model> list, ArrayList<String> id_list) {
        data = list;
        this.id_list = id_list;
        this.context = context;
for(int i=0;i<id_list.size();i++)
myarray.add("0");
    }


    @Override
    public int getCount() {
        return data.size();
    }


    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {

        View view = null;

        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);
            holder.favorite.setTag(position);
            view.setTag(holder);

if(myarray.get(Integer.parseInt(holder.favorite.getTag().toString()).equalsIgnoreCase("1")
//make your checkbox checked
else
//keep checkbox unchecked
            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
   if(  isChecked)                   myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"1");    

else
myarray.set(Integer.parseInt(holder.favorite.getTag().toString()),"0"); 

notifydatasetchanged();
            });

            holder.favorite.setTag(data.get(position));
        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }


        ViewHolder holder = (ViewHolder) view.getTag();

        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());



        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }

    class ViewHolder {
        TextView title;
        TextView model;
        ImageView image;
        CheckBox favorite;
        Boolean selected;
    }   

}

总是这样可以解决我的列表视图滚动问题..

我认为这是一个常见的错误。您需要设置此代码 holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() 在 if/else 块之外。原因是无论convertView是否=null,都要设置监听器。我知道您的代码可能需要一些安排,但我认为您可以比我做得更好,因为我的代码风格不同。这够清楚了吗?

另一个可能的错误是 holder.favorite.setTag(position)。原因是您的侦听器中的代码 Model element = (Model) holder.favorite.getTag()。您正在保存 int position 并将其类型转换为 Model class,无法工作。更改覆盖getItem,先编码再做。示例代码总结:

@Override
    public Object getItem(int position) {
        return data.get(position);   // return the Model
    }
...
holder.favorite.setTag( getItem(position) );

注意:再次 holder.favorite.setTag 应设置在 之外 if/else 块。只有 view.setTag(holder) 可以在 if 块中设置,因为它是一个新的视图对象。

除此之外,我认为您的代码设计应该可行!

Suggested code changes...

public View getView(final int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;    // different

if (convertView == null) {
   ...
   holder.favorite.setTag(data.get(position));    // different
   view.setTag(holder);                           // different

}
else {
   view = convertView;
   holder = (ViewHolder) view.getTag();    // different
}
...
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
   Model element = (Model) buttonView.getTag();    // different

变化是:

  1. 我使用不同的注释来强调代码的变化。
  2. ViewHolder holdergetView() 中声明。删除 class 内顶部的 holder 声明。我认为这是更好的编码风格,因为 holder 更接近于找到您正在使用它的位置,使其在 getView 本地。
  3. holder.favorite.setTagview.setTag的位置调换了。我认为这是一种 更安全 的编码风格。我认为在将持有人用作对象视图的参数之前先设置持有人更安全。这可能并不重要,我承认。
  4. view.getTagconvertView 不是 = null 时是必需的。当您在同一块中设置带有 view.getTag()).favorite.setTag 的标签时,您实际上是在以意外行为更改持有人的内容。
  5. 在代码 (Model) buttonView.getTag() 中,使用了 buttonView 而不是 holder.favorite。我希望这会得到正确的模型对象。

您必须保存 ViewHolder 的状态。然后在convertView == null时设置tag,在else条件下得到

看看我是怎么做的:

public class Conference_listViewAdapter extends ArrayAdapter<Model> {
    Activity context;
    LayoutInflater inflater;
    public static List<Model> data = null;
    ArrayList<String> id_list = new ArrayList<String>();

    int pos;


    public Conference_listViewAdapter(Activity context, List<Model> list, ArrayList<String> id_list) {
        super(context, R.layout.people_list_item1, list);
        this.context = context;
        this.data = list;
        this.id_list = id_list; 
    }



    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = null;       
        if (convertView == null) {
            LayoutInflater inflator = context.getLayoutInflater();
            view = inflator.inflate(R.layout.people_list_item1, null);
            final ViewHolder holder = new ViewHolder();
            holder.title = (TextView) view.findViewById(R.id.tv_name);
            holder.image = (ImageView) view.findViewById(R.id.avtaar);
            holder.favorite = (CheckBox) view.findViewById(R.id.fav);

            view.setTag(holder);

            holder.favorite.setTag(data.get(position));

            holder.favorite.setOnCheckedChangeListener(new OnCheckedChangeListener() {

                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                    
                    Model element = (Model) holder.favorite.getTag();
                    element.setSelected(buttonView.isChecked());     
                }
            });


        } else {
            view = convertView;
            ((ViewHolder) view.getTag()).favorite.setTag(data.get(position));
        }





        ViewHolder holder = (ViewHolder) view.getTag();     
        holder.favorite.setChecked(data.get(position).isSelected());
        holder.title.setText(data.get(position).getName());

        try {
            holder.image.setImageBitmap(openPhoto(Long.valueOf(id_list.get(position))));
        } catch (Exception e) {
            e.printStackTrace();
        }

        return view;
    }




    static class ViewHolder {
        protected TextView title;
        protected CheckBox favorite;
        ImageView image;
    }