Skip to content

Commit c115fa0

Browse files
author
Gilles Debunne
committed
Fixed SpellCheckerSessions leak in TextView
Bug 5709546 Change 1a22db2 created a potential leak: setText calls sendOnTextChange that now calls updateSpellCheckSpans. The original call to updateSpellCheckSpans made sure the View had been attached to a window, through the existence of the SpellChecker object. The mSpellChecker object will now only be created when the View is attached, all other spell related method will do nothing if it has not been initialized. Change-Id: I8885c12be6395e2346c0ed057bb6a275256f012b
1 parent fb90df8 commit c115fa0

File tree

1 file changed

+13
-22
lines changed

1 file changed

+13
-22
lines changed

core/java/android/widget/TextView.java

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,7 +3207,6 @@ private void setText(CharSequence text, BufferType type,
32073207
}
32083208

32093209
boolean needEditableForNotification = false;
3210-
boolean startSpellCheck = false;
32113210

32123211
if (mListeners != null && mListeners.size() != 0) {
32133212
needEditableForNotification = true;
@@ -3219,7 +3218,6 @@ private void setText(CharSequence text, BufferType type,
32193218
setFilters(t, mFilters);
32203219
InputMethodManager imm = InputMethodManager.peekInstance();
32213220
if (imm != null) imm.restartInput(this);
3222-
startSpellCheck = true;
32233221
} else if (type == BufferType.SPANNABLE || mMovement != null) {
32243222
text = mSpannableFactory.newSpannable(text);
32253223
} else if (!(text instanceof CharWrapper)) {
@@ -3308,11 +3306,6 @@ private void setText(CharSequence text, BufferType type,
33083306
sendOnTextChanged(text, 0, oldlen, textLength);
33093307
onTextChanged(text, 0, oldlen, textLength);
33103308

3311-
if (startSpellCheck && mSpellChecker != null) {
3312-
// This view has to have been previously attached for mSpellChecker to exist
3313-
updateSpellCheckSpans(0, textLength);
3314-
}
3315-
33163309
if (needEditableForNotification) {
33173310
sendAfterTextChanged((Editable) text);
33183311
}
@@ -4479,8 +4472,8 @@ protected void onAttachedToWindow() {
44794472

44804473
// Resolve drawables as the layout direction has been resolved
44814474
resolveDrawables();
4482-
4483-
updateSpellCheckSpans(0, mText.length());
4475+
4476+
updateSpellCheckSpans(0, mText.length(), true /* create the spell checker if needed */);
44844477
}
44854478

44864479
@Override
@@ -7631,7 +7624,7 @@ void sendOnTextChanged(CharSequence text, int start, int before, int after) {
76317624
}
76327625
}
76337626

7634-
updateSpellCheckSpans(start, start + after);
7627+
updateSpellCheckSpans(start, start + after, false);
76357628

76367629
// Hide the controllers as soon as text is modified (typing, procedural...)
76377630
// We do not hide the span controllers, since they can be added when a new text is
@@ -7789,17 +7782,22 @@ void spanChange(Spanned buf, Object what, int oldStart, int newStart, int oldEnd
77897782
}
77907783
}
77917784

7792-
if (newStart < 0 && what instanceof SpellCheckSpan) {
7793-
getSpellChecker().removeSpellCheckSpan((SpellCheckSpan) what);
7785+
if (mSpellChecker != null && newStart < 0 && what instanceof SpellCheckSpan) {
7786+
mSpellChecker.removeSpellCheckSpan((SpellCheckSpan) what);
77947787
}
77957788
}
77967789

77977790
/**
77987791
* Create new SpellCheckSpans on the modified region.
77997792
*/
7800-
private void updateSpellCheckSpans(int start, int end) {
7793+
private void updateSpellCheckSpans(int start, int end, boolean createSpellChecker) {
78017794
if (isTextEditable() && isSuggestionsEnabled()) {
7802-
getSpellChecker().spellCheck(start, end);
7795+
if (mSpellChecker == null && createSpellChecker) {
7796+
mSpellChecker = new SpellChecker(this);
7797+
}
7798+
if (mSpellChecker != null) {
7799+
mSpellChecker.spellCheck(start, end);
7800+
}
78037801
}
78047802
}
78057803

@@ -8970,13 +8968,6 @@ private long getCharRange(int offset) {
89708968
return packRangeInLong(offset, offset);
89718969
}
89728970

8973-
private SpellChecker getSpellChecker() {
8974-
if (mSpellChecker == null) {
8975-
mSpellChecker = new SpellChecker(this);
8976-
}
8977-
return mSpellChecker;
8978-
}
8979-
89808971
private long getLastTouchOffsets() {
89818972
SelectionModifierCursorController selectionController = getSelectionController();
89828973
final int minOffset = selectionController.getMinTouchOffset();
@@ -9930,7 +9921,7 @@ public void onItemClick(AdapterView<?> parent, View view, int position, long id)
99309921
// There is no way to know if the word was indeed added. Re-check.
99319922
// TODO The ExtractEditText should remove the span in the original text instead
99329923
editable.removeSpan(suggestionInfo.suggestionSpan);
9933-
updateSpellCheckSpans(spanStart, spanEnd);
9924+
updateSpellCheckSpans(spanStart, spanEnd, false);
99349925
} else {
99359926
// SuggestionSpans are removed by replace: save them before
99369927
SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,

0 commit comments

Comments
 (0)