Android – ListView中绑定到自定义ArrayAdapter的EditTexts – 跟踪更改

我有一个Android的活动,我有一个ListView绑定到一个自定义ArrayAdapter。 ListView的每一行都有两个EditText(数字)字段。

ArrayAdapter最初是从SQLite数据库填充的。 但是,用户可以在ListView的末尾添加一行,或者(通过长按一行)删除ListView中的任何一行。 当他们点击“保存”button时,他们的变化将持续。

通过将AfterTextChanged()事件的CustomTextWatcher附加到ArrayAdapter的getView()方法中的每个EditText(传入EditText和ArrayAdapter的项目列表中相应的对象),然后设置匹配项该对象的属性对EditText的内容。 这样在保存时我可以简单地遍历底层对象列表并进行适当的数据库更改,知道对象列表是最新的。

适配器类和CustomTextWatcher代码:

private class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; public CustomAdapter(Context context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = vi.inflate(R.layout.log_exercise_row, null); } if(wed != null) { EditText text1 = (EditText) v.findViewById(R.id.text1); EditText text2 = (EditText) v.findViewById(R.id.text2); text1.addTextChangedListener(new CustomTextWatcher(text1,wed)); text2.addTextChangedListener(new CustomTextWatcher(text2,wed)); int weight = wed.getWeight(); if(weight != -1) { text1.setText(weight+""); } int reps = wed.getReps(); if(reps != -1) { text2.setText(reps+""); } } return v; } private class CustomTextWatcher implements TextWatcher { private EditText EditText; private DataItem item; public CustomTextWatcher(EditText e, DataItem item) { this.EditText = e; this.item = item; } @Override public void afterTextChanged(Editable arg0) { String text = arg0.toString(); if(text != null && text.length() > 0) { int val; try { val =Integer.parseInt(text); } catch(NumberFormatException e) { val=-1; } if(EditText.getId()==R.id.weightEditText) { item.setWeight(val); } else if(EditText.getId()==R.id.repsEditText) { item.setRepetitions(val); } } } 

这一切都工作正常,除非项目添加或删除时发生不必要的重复EditText内容。

用一个例子来说明:

从3行开始,EditText全部为空
在第2行中,input“5”,“6”
点击“更多” – >在最后添加一个(空)行。 现在4行。
删除最后一行 – > 3行显示,但第二和第三行现在显示“5”,“6” – > ???????

看起来像ListView中的EditText对象的相对位置在重新绑定后不稳定,这是造成问题的原因。 例如,EditText对象'X'从位置3开始,然后在重新绑定之后位于位置1 – 但它仍然有一个引用位置3的数据对象的CustomTextWatcher。另一个问题是addTextChangedListener()影响已经附加到EditText的TextWatchers。

我对Android很新,所以我不确定是否有更好的方法来解决我的问题。 任何帮助表示赞赏。

Solutions Collecting From Web of "Android – ListView中绑定到自定义ArrayAdapter的EditTexts – 跟踪更改"

它看起来像一个自定义('ViewHolder')类是我所需要的,以保持EditText和其关联的数据对象之间的引用正确同步的每个数据绑定。 另外,在getView()方法中,当convertView对象为null时,将放置事件侦听器,这意味着每个EditText对象只能添加一个侦听器。

感谢http://www.vogella.de/articles/AndroidListView/article.html#listsactivity将我指向正确的方向&#x3002;

 public class CustomAdapter extends ArrayAdapter<DataItem> { private ArrayList<DataItem> items; private Activity Context; public CustomAdapter(Activity context, int textViewResourceId, ArrayList<DataItem> items) { super(context, textViewResourceId, items); this.items = items; this.Context = context; } static class ViewHolder { protected EditText weight; protected EditText reps; } public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; DataItem wed = items.get(position); if (v == null) { LayoutInflater inflator = Context.getLayoutInflater(); v = inflator.inflate(R.layout.log_exercise_row, null); final ViewHolder viewHolder = new ViewHolder(); viewHolder.text1 = (EditText) v.findViewById(R.id.text1); viewHolder.text2 = (EditText) v.findViewById(R.id.text2); viewHolder.text1.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text1)); viewHolder.text2.addTextChangedListener(new CustomTextWatcher(viewHolder, viewHolder.text2)); v.setTag(viewHolder); viewHolder.text1.setTag(wed); viewHolder.text2.setTag(wed); } else { ViewHolder holder = (ViewHolder) v.getTag(); holder.text1.setTag(wed); holder.text2.setTag(wed); } ViewHolder holder = (ViewHolder) v.getTag(); // set values if(wed.getWeight() != -1) { holder.text1.setText(wed.getWeight()+""); } else { holder.weight.setText(""); } if(wed.getRepetitions() != -1) { holder.text2.setText(wed.getRepetitions()+""); } else { holder.reps.setText(""); } return v; }