summaryrefslogtreecommitdiff
path: root/core/java/android/widget/SpellChecker.java
diff options
context:
space:
mode:
authorGilles Debunne <debunne@google.com>2011-10-27 14:38:27 -0700
committerGilles Debunne <debunne@google.com>2011-10-31 11:38:40 -0700
commite9b82808d412fa1b87954dd88579b92d0b4ab0e2 (patch)
tree2e6ea1cce763e780604a299fec397b51a340b11c /core/java/android/widget/SpellChecker.java
parentc86b8730e8c0ee930af5151cc47e6822408ac5ed (diff)
No threading issues in SpellChecker.
SpellChecker is exclusively called from the main UI thread and there are no concurrency issues. As a result, the TextView's wordIterator can safely be re-used in the parse() method. Also reset the pool of SpellParsers on language change. Change-Id: I1cc8a2750f21233754f006e40a81622730030ec8
Diffstat (limited to 'core/java/android/widget/SpellChecker.java')
-rw-r--r--core/java/android/widget/SpellChecker.java76
1 files changed, 39 insertions, 37 deletions
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 118969f93e03..82af4aa7d245 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -74,10 +74,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
private Locale mCurrentLocale;
- // Shared by all SpellParsers. Cannot be shared with TextView since it may be used
- // concurrently due to the asynchronous nature of onGetSuggestions.
- private WordIterator mWordIterator;
-
public SpellChecker(TextView textView) {
mTextView = textView;
@@ -106,19 +102,11 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
mLength = 0;
- // Change SpellParsers' wordIterator locale
- mWordIterator = new WordIterator(locale);
-
- // Stop all SpellParsers
- final int length = mSpellParsers.length;
- for (int i = 0; i < length; i++) {
- mSpellParsers[i].finish();
- }
-
- // Remove existing misspelled SuggestionSpans
- mTextView.removeMisspelledSpans((Editable) mTextView.getText());
+ // Reset the SpellParser pool: they will get re-created on demand
+ stopAllSpellParsers();
+ mSpellParsers = new SpellParser[0];
- // This class is the listener for locale change: warn other locale-aware objects
+ // This class is the global listener for locale change: warn other locale-aware objects
mTextView.onLocaleChanged();
}
@@ -135,9 +123,13 @@ public class SpellChecker implements SpellCheckerSessionListener {
mSpellCheckerSession.close();
}
+ stopAllSpellParsers();
+ }
+
+ private void stopAllSpellParsers() {
final int length = mSpellParsers.length;
for (int i = 0; i < length; i++) {
- mSpellParsers[i].finish();
+ mSpellParsers[i].stop();
}
}
@@ -192,10 +184,11 @@ public class SpellChecker implements SpellCheckerSessionListener {
if (!isSessionActive()) return;
+ // Find first available SpellParser from pool
final int length = mSpellParsers.length;
for (int i = 0; i < length; i++) {
final SpellParser spellParser = mSpellParsers[i];
- if (spellParser.isFinished()) {
+ if (!spellParser.isParsing()) {
spellParser.init(start, end);
spellParser.parse();
return;
@@ -284,7 +277,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
final int length = mSpellParsers.length;
for (int i = 0; i < length; i++) {
final SpellParser spellParser = mSpellParsers[i];
- if (!spellParser.isFinished()) {
+ if (spellParser.isParsing()) {
spellParser.parse();
}
}
@@ -358,16 +351,23 @@ public class SpellChecker implements SpellCheckerSessionListener {
private Object mRange = new Object();
public void init(int start, int end) {
- ((Editable) mTextView.getText()).setSpan(mRange, start, end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ setRangeSpan((Editable) mTextView.getText(), start, end);
+ }
+
+ public void stop() {
+ removeRangeSpan((Editable) mTextView.getText());
+ }
+
+ public boolean isParsing() {
+ return ((Editable) mTextView.getText()).getSpanStart(mRange) >= 0;
}
- public void finish() {
- ((Editable) mTextView.getText()).removeSpan(mRange);
+ private void setRangeSpan(Editable editable, int start, int end) {
+ editable.setSpan(mRange, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
- public boolean isFinished() {
- return ((Editable) mTextView.getText()).getSpanStart(mRange) < 0;
+ private void removeRangeSpan(Editable editable) {
+ editable.removeSpan(mRange);
}
public void parse() {
@@ -376,22 +376,23 @@ public class SpellChecker implements SpellCheckerSessionListener {
final int start = editable.getSpanStart(mRange);
final int end = editable.getSpanEnd(mRange);
+ final WordIterator wordIterator = mTextView.getWordIterator();
int wordIteratorWindowEnd = Math.min(end, start + WORD_ITERATOR_INTERVAL);
- mWordIterator.setCharSequence(editable, start, wordIteratorWindowEnd);
+ wordIterator.setCharSequence(editable, start, wordIteratorWindowEnd);
// Move back to the beginning of the current word, if any
- int wordStart = mWordIterator.preceding(start);
+ int wordStart = wordIterator.preceding(start);
int wordEnd;
if (wordStart == BreakIterator.DONE) {
- wordEnd = mWordIterator.following(start);
+ wordEnd = wordIterator.following(start);
if (wordEnd != BreakIterator.DONE) {
- wordStart = mWordIterator.getBeginning(wordEnd);
+ wordStart = wordIterator.getBeginning(wordEnd);
}
} else {
- wordEnd = mWordIterator.getEnd(wordStart);
+ wordEnd = wordIterator.getEnd(wordStart);
}
if (wordEnd == BreakIterator.DONE) {
- editable.removeSpan(mRange);
+ removeRangeSpan(editable);
return;
}
@@ -454,24 +455,25 @@ public class SpellChecker implements SpellCheckerSessionListener {
// iterate word by word
int originalWordEnd = wordEnd;
- wordEnd = mWordIterator.following(wordEnd);
+ wordEnd = wordIterator.following(wordEnd);
if ((wordIteratorWindowEnd < end) &&
(wordEnd == BreakIterator.DONE || wordEnd >= wordIteratorWindowEnd)) {
wordIteratorWindowEnd = Math.min(end, originalWordEnd + WORD_ITERATOR_INTERVAL);
- mWordIterator.setCharSequence(editable, originalWordEnd, wordIteratorWindowEnd);
- wordEnd = mWordIterator.following(originalWordEnd);
+ wordIterator.setCharSequence(editable, originalWordEnd, wordIteratorWindowEnd);
+ wordEnd = wordIterator.following(originalWordEnd);
}
if (wordEnd == BreakIterator.DONE) break;
- wordStart = mWordIterator.getBeginning(wordEnd);
+ wordStart = wordIterator.getBeginning(wordEnd);
if (wordStart == BreakIterator.DONE) {
break;
}
}
if (scheduleOtherSpellCheck) {
- editable.setSpan(mRange, wordStart, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ // Update range span: start new spell check from last wordStart
+ setRangeSpan(editable, wordStart, end);
} else {
- editable.removeSpan(mRange);
+ removeRangeSpan(editable);
}
spellCheck();