Java TextWatcher中的IndexOutOfBoundsException

Java TextWatcher中的IndexOutOfBoundsException,java,android,indexoutofboundsexception,android-textwatcher,Java,Android,Indexoutofboundsexception,Android Textwatcher,在我的应用程序中,我想在EditText中跟踪输入。每次用户修改EditText中的字符时,我要跟踪: 如果添加/删除了字符 从中添加/删除字符的索引,以及 添加/删除了什么字符 我使用TextWatcher来实现这一点。到目前为止,我的方法一直运作良好。但最近我在我的生产应用程序中遇到了3次与IndexOutOfBoundsException相关的崩溃。我注意到的一点是,所有的崩溃都发生在操作系统版本为6.0.1的Galaxy S7上 我正试图找出一个好方法来理解和修复这次崩溃。请参考下面的代

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

  • 如果添加/删除了字符
  • 从中添加/删除字符的索引,以及
  • 添加/删除了什么字符
  • 我使用
    TextWatcher
    来实现这一点。到目前为止,我的方法一直运作良好。但最近我在我的生产应用程序中遇到了3次与
    IndexOutOfBoundsException
    相关的崩溃。我注意到的一点是,所有的崩溃都发生在操作系统版本为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();
        }
    }
    
    查看异常中的索引,我假设
    addCharIndex
    计算不正确。这意味着我对beforeTextChanged的参数理解不正确,或者未按预期顺序调用
    TextWatcher
    方法,或者使用更新的参数多次调用它们,这会扰乱我在中计算
    addCharIndex
    的逻辑
    在文本更改之前

    任何关于如何解决这个问题的帮助和见解都将不胜感激


    谢谢。

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

    你的问题实际上发生在那之前。因为当你删除字符时,你不会更新你的
    addCharIndex
    。如果上一个索引是10,并且删除了8个字符,则索引仍然是10,但长度仅为2

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

    s.charAt(deleteCharIndex-1)=''

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


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

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

    你的问题实际上发生在那之前。因为当你删除字符时,你不会更新你的
    addCharIndex
    。如果上一个索引是10,并且删除了8个字符,则索引仍然是10,但长度仅为2

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

    s.charAt(deleteCharIndex-1)=''

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


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

    为什么这个问题被否决了?如果有人告诉我这个问题有什么问题,我将不胜感激,这样我就可以对这个问题作出适当的修改。为什么这个问题被否决了?如果有人告诉我这个问题有什么问题,我将不胜感激,这样我就可以对这个问题进行适当的修改。谢谢你的回答。我看到了您指出的故障,我将提出修改建议以修复它。但是,崩溃报告中的stacktrace指向“s.charAt(addedCharacterIndex)=='@'”行。这条线上的崩溃是你刚才指出的错误的副产品吗?谢谢你的回答。我看到了您指出的故障,我将提出修改建议以修复它。但是,崩溃报告中的stacktrace指向“s.charAt(addedCharacterIndex)=='@'”行。这条线上的崩溃是您刚才指出的错误的副产品吗?
    java.lang.IndexOutOfBoundsException:  charAt: 24 >= length 23
    
    java.lang.IndexOutOfBoundsException:  charAt: 202 >= length 198
    
    java.lang.IndexOutOfBoundsException:  charAt: 1 >= length 1