【问题标题】:TextWatcher.onTextChanged called multiple times多次调用 TextWatcher.onTextChanged
【发布时间】:2015-10-27 18:09:16
【问题描述】:

我已经阅读了一些有关此问题的主题,但找不到完整的答案。 我有一个 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",正如另一个帖子中所建议的那样。

这是 Activity 启动并填充 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 个调用,因为没有真正改变)。

从现在开始,每次更改都会根据需要进行一次调用。

更新:我创建了一个布尔数组来指示 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

【问题讨论】:

  • 在 ListView / 适配器项之外使用 EditText 时是否同样工作?
  • 自己没试过,但是根据其他帖子(例如this one),是的。
  • 但我试过了,没有,没有多余的电话,你自己试试,这样你就可以找出罪魁祸首了
  • 谢谢,我会试试的,虽然它不能解决我的问题,因为我愿意使用 ListView。
  • 好的,先试试简单的EditText,然后在适配器只有一个Item的ListView中使用,这是一个调查

标签: java android textwatcher


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    另一种解决方案是检查字段(EditText 或 TextView)是否为脏。

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (mTextView.isDirty())
                        doWork();
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-04
      • 2010-10-03
      • 2018-10-19
      • 2013-03-31
      • 2019-12-16
      • 2015-01-16
      • 2017-12-17
      • 1970-01-01
      相关资源
      最近更新 更多