0

在我的应用程序中,我想跟踪EditText. 每次用户修改EditText我要跟踪的字符时:

  1. 如果添加/删除了一个字符
  2. 添加/删除字符的索引处和
  3. 添加/删除了什么字符

我用TextWatcher它来实现这一点。到目前为止,我的方法一直运行良好。但最近我IndexOutOfBoundsException的生产应用程序发生了 3 次崩溃。我注意到的一件事是所有崩溃都发生在操作系统版本为 6.0.1 的 Galaxy S7 上。

我正在尝试找出一种理解和修复此崩溃的好方法。请参考下面的代码

public class EditTextMonitor extends Activity implements TextWatcher {
    private EditText etInputText;

    private int deleteCharIndex = -1, addCharIndex = -1;
    private char deleteChar;
    private boolean wasCharDeleted;
    private String prevCharSeq = "";

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);
        etInputText = (EditText) findViewById(R.id.etInputText);
    }

    // Add TextChangedListener here to prevent call to text watcher methods upon switching
    // orientation
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        etInputText.addTextChangedListener(this);
    }

    /*
      This method is called to notify you that, within s, the count characters beginning at
      start have just replaced old text that had length before. It is an error to attempt to
      make changes to s from this callback.
    */
    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    /*
      This method is called to notify you that, within s, the count characters beginning at start
      are about to be replaced by new text with length after.
      It is an error to attempt to make changes to s from this callback.
    */
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        // if count > after then its a char delete cause the no. of chars in 's'
        // will decrease when the text change is complete.
        // If count < after
        // then its a char addition cause the no. of chars in 's'
        // will increase when the text change is complete.
        if (count > after) {
            // CHARACTER DELETION
            // As 'count' is no. of chars being replaced from 'start' by
            // 'after' no. of chars, (start+count)-1 will be the index of the
            // char that that will be deleted.
            deleteCharIndex = (start + count) - 1;
            deleteChar = s.charAt(deleteCharIndex);
            wasCharDeleted = true;
        } else if (count < after) {
            // CHARACTER ADDITION
            // As 'count' is no. of chars being replaced from 'start' by
            // 'after' no. of chars, (start+after)-1 will will be the index of the
            // char that will be added.
            wasCharDeleted = false;
            addCharIndex = (start + after) - 1;
        } else {
            // Extra call to the text changed method with no change in 's'.
            // Android framework bug??
            wasCharDeleted = false;
            Log.d(TAG, "------EXTRA CALL TO BEFORETEXTCHANGED------");
        }
    }

    @Override
    public void afterTextChanged(Editable s) {
        // Don't process if redundant call to afterTextChanged method.
        // A framework bug??
        if (!prevCharSeq.equals(s.toString())) {
            if (wasCharDeleted) {
                // handle char delete

                if (deleteChar == 'x'
                        && (s.length() == 0 || s.charAt(deleteCharIndex - 1) == ' ')) {
                    // Business logic to deal with the case where the deleted char was an independent 'x'
                } else {
                    // Business logic to deal with the case where deleted char was anything other than an independent 'x'.
                }
            } else {
                // handle char addition

                ***if (s.charAt(addCharIndex) == 'x'// CRASH OCCURS ON THIS LINE <-----------------***
                        && (s.length() == 1 || s.charAt(addCharIndex - 1) == ' ')) {
                    // Business logic to deal with the case where added char is an independent 'x'
                } else {
                    // Business logic to deal with the case where added char is anything other than an independent 'x'
                }
            }
        }
        prevCharSeq = s.toString();
    }
}

到目前为止的 3 次崩溃是:

java.lang.IndexOutOfBoundsException:  charAt: 24 >= length 23

java.lang.IndexOutOfBoundsException:  charAt: 202 >= length 198

java.lang.IndexOutOfBoundsException:  charAt: 1 >= length 1

查看异常中的索引,我假设addCharIndex没有正确计算。这意味着要么我对参数的理解beforeTextChanged不正确,要么TextWatcher方法没有按预期顺序调用,或者它们被多次调用并更新了参数,这弄乱了我计算addCharIndexin的逻辑beforeTextChanged

任何有关如何解决此问题的帮助和见解将不胜感激。

谢谢。

4

1 回答 1

2

这不是设备问题。这是一个逻辑问题。

您的问题实际上发生在此之前。因为当您删除字符时,您不会更新您的addCharIndex. 如果之前的索引是 10,而你删除了 8 个字符,那么你的索引仍然是 10,但你的长度只有 2。

如果您在输入中xd输入然后删除,x您将因此崩溃indexOutOfBoundsException,因为您的 if 语句执行以下操作:

s.charAt(deleteCharIndex - 1) == ' '

但是由于您已删除x字符,因此您的长度现在为 1,但您正在检查 0 或上述语句,这就是您得到错误的方式。如果您不知道 if 语句中是否有 OR (||),它将检查每个条件,直到它达到真正的结果。

有很多方法可以修复它,一种方法是检查s.length() > 1这种方法当你做deleteCharIndex - 1的最低点是 0 时。

于 2017-03-08T23:18:19.660 回答