TextWatcher.onTextChanged 被多次调用

2024-05-01

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

问题是 LisView 元素正在被回收,因此旧的 TextWatcher 在回收行后仍然附加。因此,每次调用 getView 时,都会添加一个新的 TextWatcher,而旧的 TextWatcher 仍附加到 EditText。不幸的是,没有函数可以删除附加的所有旧 TextWatcher,因此唯一的解决方案是创建一个自定义 EditText,在其中保留对所有 TextWatcher 的引用,然后创建一个自定义函数以在回收 getView 中的 View 时将它们全部删除。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TextWatcher.onTextChanged 被多次调用 的相关文章

随机推荐