首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IndexOutOfBoundsException in TextWatcher

IndexOutOfBoundsException in TextWatcher
EN

Stack Overflow用户
提问于 2017-03-08 20:47:41
回答 1查看 461关注 0票数 0

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

  1. 如果添加/删除字符
  2. 添加/删除字符的索引,以及
  3. 添加/删除了哪些字符

为了实现这一点,我使用TextWatcher。到目前为止,我的方法一直很好。但最近,我的生产应用程序中出现了3次IndexOutOfBoundsException崩溃。我注意到的一件事是,所有的崩溃都发生在Galaxy6.0.1版的GalaxyS7上。

我正在努力想出一个好的方法来理解和解决这次坠机。请参考下面的代码

代码语言:javascript
复制
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起撞车事故是:

代码语言:javascript
复制
java.lang.IndexOutOfBoundsException:  charAt: 24 >= length 23

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

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

查看异常中的索引,我假设addCharIndex没有得到正确的计算。这意味着我对beforeTextChanged参数的理解是不正确的,或者TextWatcher方法没有按预期的顺序调用,或者使用更新的参数多次调用它们,这会扰乱我的逻辑以计算beforeTextChanged中的addCharIndex

对如何解决这一问题的任何帮助和见解将不胜感激。

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2017-03-08 23:18:19

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

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

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

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

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

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42681639

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档