6

我在ListView上方有一个CheckBox,其中有复选框项。因此,当我检查复选框时,我应用notifyDataSetChanged()来检查所有检查列表中的所有项目。所以当时我得到了两次getView方法的日志,这意味着当我只拨打一次notifyDataSetChanged()时,getView会被调用两次。那么,谁能告诉我为什么我要两次获取日志?此外为什么getView()被调用两次?带CheckBox的ListView的奇怪行为

主类 -

checkAll = (CheckBox) findViewById(R.id.my_check_box); 
     checkAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 

      @Override 
      public void onCheckedChanged(CompoundButton checkbox, boolean arg1) { 
       adapter.notifyDataSetChanged(); 
      } 
     }); 

代码适配器类别 -

public class myAdapter extends ArrayAdapter<Model> { 

    private final List<Model> list; 
    private final Activity context; 
    private CheckBox checkAll; 

    public myAdapter(Activity context, List<Model> list, CheckBox checkAll) { 
     super(context, R.layout.row, list); 
     this.context = context; 
     this.list = list; 
     this.checkAll = checkAll; 

    } 

    static class ViewHolder { 
     protected TextView text; 
     protected CheckBox checkbox; 
    } 

    @Override 
    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.row, null); 
      final ViewHolder viewHolder = new ViewHolder(); 
      viewHolder.text = (TextView) view.findViewById(R.id.label); 
      viewHolder.checkbox = (CheckBox) view.findViewById(R.id.check); 
      viewHolder.checkbox 
        .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 

         @Override 
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
          Model element = (Model) viewHolder.checkbox.getTag(); 
          element.setSelected(buttonView.isChecked()); 
         } 
        }); 
      view.setTag(viewHolder); 
      viewHolder.checkbox.setTag(list.get(position)); 
     } else { 
      view = convertView; 
      ((ViewHolder) view.getTag()).checkbox.setTag(list.get(position)); 
     } 
     ViewHolder holder = (ViewHolder) view.getTag(); 
     holder.text.setText(list.get(position).getName()); 


     if(checkAll.isChecked() == true){ 
      System.out.println(position+" checked th position"); 
     } 
     else if(checkAll.isChecked() == false){ 
      System.out.println(position+" not checked th position"); 
     } 

     holder.checkbox.setChecked(list.get(position).isSelected());  
     return view; 
    } 
} 

logcat的输出当我adapter.notifyDataSetChanged();上CheckAll checkboxs检查更改侦听器。

11-30 20:31:33.751: INFO/System.out(1300): 0 checked th position 
11-30 20:31:33.761: INFO/System.out(1300): 1 checked th position 
11-30 20:31:33.770: INFO/System.out(1300): 2 checked th position 
11-30 20:31:33.780: INFO/System.out(1300): 3 checked th position 
11-30 20:31:33.810: INFO/System.out(1300): 4 checked th position 
11-30 20:31:33.810: INFO/System.out(1300): 0 checked th position 
11-30 20:31:33.831: INFO/System.out(1300): 1 checked th position 
11-30 20:31:33.831: INFO/System.out(1300): 2 checked th position 
11-30 20:31:33.851: INFO/System.out(1300): 3 checked th position 
11-30 20:31:33.860: INFO/System.out(1300): 4 checked th position 

你可以看到我的Logcat输出获得了两次相同的输出。那么谁能说出这是为什么?

+1

这个问题也引起我的兴趣... +1 –

+2

http:// stackoverflow。com/questions/2618272/custom-listview-adapter-getview-method-being-called-multiple-times-and-in-no-co检查这个 – MKJParekh

+0

@Lalit Poptani你滚动吗? – Venky

回答

5

尝试使你的ListView高度fill_parent

Lisiview试图根据提供的空间调整一下,这是我学到的东西,看起来这是背后的原因。

看看是否有帮助。

+2

这意味着当你想在你的列表视图的一半设置屏幕..你无法解决上述问题? – MKJParekh

+0

可以在屏幕底部的一半处用fill_parent .............. – viv

+0

如果你想在一半的屏幕上设置你的列表视图,你可以使用android:layout_weight作为那个 –

0

这是bacause viewcurl里面checkchangelistener会随着列表滚动而改变。所以在复选框和viewHolder之间没有映射可以使用这种方式来实现。

创建sepatera类checkchangelistener实现checnChecnglistener。通过构造函数传递checkchangelistener。

EG。 getView

class MyCheckChangeLsitenet implements CompoundButton.OnCheckedChangeListener 

ViewHolder viewHolder 
MyCheckChangeLsitenet(ViewHolder viewHolder) 
{ 
this.viewHolder = viewHolder ; 
} 
         @Override 
         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
          Model element = (Model) viewHolder.checkbox.getTag(); 
          element.setSelected(buttonView.isChecked()); 
         } 
        }); 

在GetView

viewHolder.checkbox .setOnCheckedChangeListener(新MycheckChangeListenet(viewHolder))之外

+1

虽然它给出了相同的问题,但我目前不在滚动列表。 –

+0

忘记术语滚动。试图让你熟悉内部的listView处理。通过描述的方式。它会解决你的问题 –

3

这是不是一个真正的回答你的问题 - 它只是它伤害了我的眼睛有点当我看到这一点:

if(checkAll.isChecked() == true){ 
    System.out.println(position+" checked th position"); 
} 
else if(checkAll.isChecked() == false){ 
    System.out.println(position+" not checked th position"); 
} 

if-statement需要boolean表达,因为该方法isChecked()回报boolean孤单无需将其与true/false进行匹配。另外,由于boolean只能是truefalse,因此不需要检查两者。总之,你可以煮上面下来:

if(checkAll.isChecked()) 
    System.out.println(position+" checked th position"); 
else 
    System.out.println(position+" not checked th position"); 

这是更漂亮:-)

不要认为这是你的编程技能的批判 - 只是把它作为学习oppertunity。

+0

那么它只是一个演示应用程序,以获得有关我的问题的确切想法。非常感谢。 –

+0

这很搞笑,kaspermoerch!试试这个: 'System.out.println(position +(checkAll.isChecked()?“checked th position”:“not checked th position”));' –

+0

这也可以,Jeff。但我确实发现三元运算符应谨慎使用。它并不总是提高可读性。 – kaspermoerch