2016-11-21 19 views
0

我的應用程序活動顯示了一個列表視圖,通過一個BaseAdapter的自定義實現 填充。項目由一個progressBar和一個CheckBox組成。BaseAdapter.notifyDataSetChanged()隱藏用戶的點擊

progressBars值由後臺線程通過使用調用BaseAdapter.notifyDataSetChanged()的Handler來更新。 在這個應用程序中,用戶應該能夠檢查複選框。

問題是,它似乎notifyDataSetChanged()隱藏或關閉用戶對CheckBox的點擊。 會發生什麼事是onClickListener.onClick()被稱爲類似用戶點擊的1/5。

在開始時,我認爲由BaseAdapter.getView()設置的值會覆蓋由用戶在CheckBox上的點擊設置的任何值。於是,我就在getView(像這樣):

if (checkBox.isChecked != data.isChecked(){ 
    checkBox.setOnCheckedChangeListener(null); 
    checkBox.setChecked(data.isChecked()); 
    checkBox.setOnCheckedChangeListener(cbClickListener); 
} 

有沒有變化,加入了日誌中onClickListener.onClick()清楚地表明的onClick不叫每次。 我該怎麼辦?

這裏的適配器代碼,這是非常經典:

class InputsConfAdapter extends BaseAdapter { 
    private static LayoutInflater inflater = null; 
    private final Model model; 
    private final inputsConfAdapterInterface handler; 
    private int[] positions; 

    //--------------------------------------------------------------------------------------------------- 

    class CbClickListener implements CheckBox.OnCheckedChangeListener{ 

     int inputId; 

     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      handler.setFailSafe((byte) inputId, isChecked); 
     } 
    } 
    //--------------------------------------------------------------------------------------------------- 

    public InputsConfAdapter(LayoutInflater inflater, Model model, inputsConfAdapterInterface handler) { 
     super(); 
     InputsConfAdapter.inflater = inflater; 
     this.handler = handler; 
     this.model = model; 
    } 

    @Override 
    public int getCount() { 
     return model.inputs.length; 
    } 

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

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

    @Override 
    public View getView(int i, View view, ViewGroup viewGroup) { 
     if (view == null) { 
      view = inflater.inflate(R.layout.theIem, null); 
      ViewHolder viewHolder = new ViewHolder(); 
      viewHolder.pbPosition = (ProgressBar) view.findViewById(R.id.pbPosition); 
      viewHolder.checkBox = (CheckBox) view.findViewById(R.id.cb); 

      final CbClickListener cbClickListener = new CbClickListener(); 
      viewHolder.checkBox.setOnCheckedChangeListener(cbClickListener); 
      viewHolder.cbClickListener = new CbClickListener(); 

      view.setTag(viewHolder); 
     } 

     final ViewHolder viewHolder = (ViewHolder) view.getTag(); 
     final CheckBox checkBox = viewHolder.checkBox; 
     final ProgressBar pbPosition = viewHolder.pbPosition; 
     final CbClickListener cbClickListener = viewHolder.cbClickListener; 

     final Input data = model.inputs[i]; 

//--- progressBar 
     if (positions != null) 
      pbPosition.setProgress(positions[i]); 

//--- checkBox 
     cbClickListener.inputId = i; 
     checkBox.setOnCheckedChangeListener(null); 
     checkBox.setChecked(data.isChecked()); 
     checkBox.setOnCheckedChangeListener(cbClickListener); 
     return view; 
    } 

    @Override 
    public boolean hasStableIds() { 
     return true; 
    } 

    @Override 
    public int getViewTypeCount() { 
     return 1; 
    } 

    public void serPositions(int[] positions) { 
     this.positions = positions; 
    } 

    private class ViewHolder { 
     public CheckBox checkBox; 
     public ProgressBar pbPosition; 
     CbClickListener cbClickListener; 

     public ViewHolder() { 

     } 
    } 

    public interface inputsConfAdapterInterface { 
     void setFailSafe(byte inputId, boolean value); 
    } 
} 

更新@Khaled:在接收列表視圖的片段。 有一個「同步」:

private final Synchronizer synchronizer = new Synchronizer(new Handler(), new DefaultListener() { 
     @Override 
     public void ValuesReceived(ValueStruct values) { 
      if (getActivity() != null) { 
       adapter.serPositions(values.values); 
       adapter.notifyDataSetChanged(); 
      } 
     } 
    }); 

的更新線程調用synchronizer.valuesReceived(),該職位在處理程序可運行在 GUI線程實例化:

public interface ISink { 
    void ValueReceived(
     ValueStruct inputValue 
    ); 
} 


public class defaultListener implements ISink { 
} 


public class Synchronizer implements ISink { 
    private ISink sink; 
    private Handler handler; 

    public Synchronizer(Handler handler, ISink sink) { 
     this.handler = handler; 
     this.sink = sink; 
    } 

    private class ValueRunnable implements Runnable { 
     ValueStruct s; 

     ValueRunnable(ValueStruct s) { 
      this.s = new ValueStruct(s); 
     } 

     @Override 
     public void run() { 
      sink.ValuesReceived(s); 
     } 
    } 

    @Override 
    public void ValuesReceived(ValueStruct s) { 
     handler.post(new ValueRunnable(s)); 
    } 
} 
+0

當您通過您的列表中滾動出現這種情況? –

+0

也不是特別的。它總是發生。 – Julien

回答

0

這裏就是我做來解決這個問題。這不是很令人滿意,但它的工作原理。 這個想法是對每個進度條進行手動更新,而不是使用notifyDataSetChanged()。

在adapater中,我添加了一個ArrayList來存儲進度條。 在此,如果結束:

public View getView(int i, View view, ViewGroup viewGroup) { 
     if (view == null) { 

我加

bars.add(viewHolder.pbPosition); 

爲了使每個進度知道它是與商品相關的,在

@Override 
    public View getView(int i, View view, ViewGroup viewGroup) { 

我添加結束

pbPosition.setTag(i); 

我刪除了對適配器的呼叫。notifyDataSetChanged();

我改變setPositions(...),以

public void serPositions(int[] positions) { 
    for (ProgressBar bar : 
      bars) { 
     int index = (int) bar.getTag(); 
     bar.setProgress(positions[index]); 
    } 
} 
0

你可能會點擊列表項而不是複選框。要解決此問題,請在xml中使複選框不可點擊並處理檢查點擊整個項目。

+0

嗯,這只是一種解決方法,實際上,在現實生活中,我也在同一個iitem上擁有editText,因此我需要確定每個項目的點擊次數。 – Julien

0

我想你應該考慮使用OnCheckedChangeListener代替OnClickListener

checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) { 
      handler.setFailSafe((byte) inputId, isChecked); 
     } 
    }); 
+0

嗯,你說的對,最好用這個。我做到了,但這並沒有改變凌亂的行爲。我會在主帖中改變。 – Julien

+0

@Julien我認爲你的問題是,你在每個項目上使用相同的偵聽器,你是否嘗試過在你的適配器中實現OnCheckedChangeListener? – Khaled

+0

我對每個顯示的項目使用不同的偵聽器:'最終的CbClickListener cbClickListener =新的CbClickListener();'我沒有提到的是我測試了代碼而沒有後臺更新,它工作的很好。 – Julien