TextWatcher.onTextChanged多次调用

时间:2015-10-27 18:09:16

标签: java android textwatcher

我已经阅读了一些有关此问题的主题,但找不到完整的答案。 我有一个包含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

2 个答案:

答案 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();
            }