+
+ } // DictionaryListAdapter
+
+ private final class SearchOperation implements Runnable {
+ SearchOperation previousSearchOperation;
+
+ final LanguageListAdapter listAdapter;
+ final LanguageData languageData;
+ final String searchText;
+ final AtomicBoolean interrupted = new AtomicBoolean(false);
+ boolean finished = false;
+
+ SearchOperation(final LanguageListAdapter listAdapter,
+ final String searchText, final SearchOperation previousSearchOperation) {
+ this.listAdapter = listAdapter;
+ this.languageData = listAdapter.languageData;
+ this.searchText = searchText;
+ this.previousSearchOperation = previousSearchOperation;
+ }
+
+ public void run() {
+ if (previousSearchOperation != null) {
+ previousSearchOperation.stopAndWait();
+ }
+ previousSearchOperation = null;
+
+ Log.d(LOG, "SearchOperation: " + searchText);
+ final int indexLocation = languageData.lookup(searchText, interrupted);
+ if (interrupted.get()) {
+ return;
+ }
+ final IndexEntry indexEntry = languageData.sortedIndex.get(indexLocation);
+
+ Log.d(LOG, "SearchOperation completed: " + indexEntry.toString());
+ uiHandler.post(new Runnable() {
+ public void run() {
+ // Check is just a performance operation.
+ if (!interrupted.get()) {
+ // This is safe, because it checks that the listAdapter hasn't changed.
+ jumpToRow(listAdapter, indexEntry.startRow);
+ }
+ }
+ });
+
+ synchronized (this) {
+ finished = true;
+ this.notifyAll();
+ }
+ }
+
+ public void stopAndWait() {
+ interrupted.set(true);
+ synchronized (this) {
+ while (!finished) {
+ Log.d(LOG, "stopAndWait: " + searchText);
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG, "Interrupted", e);
+ }
+ }
+ }
+ }
+
+
+ }