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