0

내 앱에서 EditText의 입력을 추적하고 싶습니다. 사용자가 EditText에 문자를 수정 때마다 내가 추적하려면 :TextWatcher의 IndexOutOfBoundsException

  1. 캐릭터가 추가 된 경우/
  2. 있는 캐릭터가 추가/삭제 및
  3. 무엇 문자 한에서/인덱스 삭제 추가/삭제

나는 이것을 달성하기 위해 TextWatcher을 사용합니다. 내 접근 방식은 지금까지 제대로 작동했습니다. 하지만 최근에 내 프로덕션 앱에서 IndexOutOfBoundsException으로 3 번 충돌했습니다. 제가 언급 한 한 가지는 모든 충돌이 Galaxy S7 OS 버전 6.0.1에서 발생했기 때문입니다.

이 충돌을 이해하고 해결할 수있는 좋은 방법을 찾으려고합니다. 지금까지왔다

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 메서드가 예상 된 순서로 호출되지 않았거나 beforeTextChangedaddCharIndex을 계산하는 논리를 엉망으로 만드는 업데이트 된 인수로 여러 번 호출되었습니다.

이 문제를 해결하는 방법에 대한 도움과 통찰력을 주시면 감사하겠습니다.

감사합니다.

+0

0 왜이 질문을 downvoted했다입니다 deleteCharIndex - 1을 할 때 s.length() > 1이 방법을 확인하는 것입니다? 내가 질문에 대한 적절한 변경을 할 수 있도록 질문의 문제점이 무엇인지에 대해 말하면 감사 할 것입니다. – rbing

답변

1

이것은 장치 문제가 아닙니다. 이것은 논리적 인 문제입니다.

문제는 그 전에 실제로 발생합니다. 문자를 삭제할 때 addCharIndex을 업데이트하지 않기 때문입니다. 이전 색인이 10이고 8자를 삭제 한 경우 색인은 여전히 ​​10이지만 길이는 2입니다.

xd을 입력 한 다음 x을 삭제하면 오류가 발생합니다. 당신의 if 문은 다음을 수행하기 때문이다 indexOutOfBoundsException 결과 :

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

있지만 x 문자를 삭제 한 이후 길이가 지금은 1이지만이 0 또는 위의 문을 검사하고 어떤 방법입니다 당신의 오류를 얻으십시오. if 문에 OR (||)이 있는지 여부를 모르는 경우 실제 결과에 도달 할 때까지 모든 조건을 검사합니다. 그것을 해결하는 방법에는 여러 가지가 있습니다

는 한 가지 방법은 당신이 공격 할 수있는 가장 낮은 지점

+0

답변 해 주셔서 감사합니다. 나는 당신이 지적한 잘못을보고 그것을 수정하기위한 제안 된 변경을 할 것입니다. 그러나 충돌 보고서의 스택 추적은 "s.charAt (addedCharacterIndex) == '@'"행을 가리 킵니다.이 줄의 충돌이 방금 지적한 버그의 부산물입니까? – rbing