我已经阅读了一些有关此问题的主题,但找不到完整的答案。 我有一个包含3行的ListView,每行包含一个TextView和一个EditText,以及一个扩展BaseAdapter的自定义适配器。
这是适配器的getView函数:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if(convertView == null) {
LayoutInflater inflater = mActivity.getLayoutInflater();
convertView = inflater.inflate(R.layout.settings_column, null);
mTxtValue = (EditText) convertView.findViewById(R.id.settings_value);
mTxtValue.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (tryParseInt(s.toString())) {
RowsList.get(position).setDuration(Integer.parseInt(s.toString()));
System.out.println("position: " + position + ", value: " + s.toString());
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
}
ColorColumn colorColumn = RowsList.get(position);
mTxtValue.setText(String.valueOf(colorColumn.getDuration()));
return convertView;
}
正如您所看到的,每次更改值时,我都会尝试使用EditText值更新名为RowsList的ColorColumn列表。由于某种原因,onTextChanged方法调用次数过多,因此会在列表中放入错误数据。 EditText的inputType为android:inputType="number|textNoSuggestions"
,如另一个帖子所示。
这是启动活动并填充ListView时显示的日志:
10-27 19:30:15.238 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 1
10-27 19:30:15.242 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:15.244 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:15.317 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:15.325 19845-19845/com.busalert.www.busalert I/System.out: position: 1, value: 2
10-27 19:30:15.333 19845-19845/com.busalert.www.busalert I/System.out: position: 2, value: 3
10-27 19:30:15.346 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:15.350 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:15.353 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:15.388 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:15.394 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:15.398 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
尽可能地,每个位置的第一次出现是正确的,但是有9个额外的呼叫。
这是用户首次输入EditText的一个日志:
10-27 19:30:21.226 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:21.230 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:21.231 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:21.356 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:21.357 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:21.363 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:21.369 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 19:30:21.370 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 19:30:21.376 19845-19845/com.busalert.www.busalert I/System.out: position: 0, value: 3
再次,9个额外的呼叫(应该有0个呼叫,因为没有真正改变)。
从此处开始,每次更改都会根据需要进行一次调用。
UPDATE:我创建了一个布尔数组来指示TextWatcher是否已经添加到每个EditText中,因此我确保每个都只有一个。添加完成后,活动开始时有6个调用(3个额外),第一次单击EditText时没有调用。这是新的日志(2,3和4是多余的):
10-27 20:02:49.765 29637-29637/com.busalert.www.busalert I/System.out: position: 0, value: 1
10-27 20:02:49.767 29637-29637/com.busalert.www.busalert I/System.out: position: 0, value: 2
10-27 20:02:49.769 29637-29637/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 20:02:49.827 29637-29637/com.busalert.www.busalert I/System.out: position: 0, value: 3
10-27 20:02:49.834 29637-29637/com.busalert.www.busalert I/System.out: position: 1, value: 2
10-27 20:02:49.840 29637-29637/com.busalert.www.busalert I/System.out: position: 2, value: 3
答案 0 :(得分:0)
问题是LisView元素正在被回收,因此在回收行之后仍然附加了旧的TextWatcher。因此,每次调用getView时,都会添加一个新的TextWatcher,而旧的TextWatcher仍然附加到EditText。遗憾的是,没有删除所有旧TextWatchers的功能,因此唯一的解决方案是创建一个自定义EditText,您可以在其中保留对所有TextWatcher的引用,然后创建一个自定义函数,以便在getView中回收View时将它们全部删除。
答案 1 :(得分:0)
另一种解决方案是检查字段(EditText或TextView)是否为脏。
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (mTextView.isDirty())
doWork();
}