diff --git a/java/src/com/android/inputmethod/latin/AutoDictionary.java b/java/src/com/android/inputmethod/latin/AutoDictionary.java index 3d76dc301..da9dd6eb9 100644 --- a/java/src/com/android/inputmethod/latin/AutoDictionary.java +++ b/java/src/com/android/inputmethod/latin/AutoDictionary.java @@ -96,11 +96,14 @@ public class AutoDictionary extends ExpandableDictionary { return frequency >= VALIDITY_THRESHOLD; } + @Override public void close() { mOpenHelper.close(); + super.close(); } - private void loadDictionary() { + @Override + public void loadDictionaryAsync() { // Load the words that correspond to the current input locale Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); if (cursor.moveToFirst()) { @@ -183,15 +186,6 @@ public class AutoDictionary extends ExpandableDictionary { return c; } - private boolean insert(ContentValues values) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - long rowId = db.insert(AUTODICT_TABLE_NAME, Words.WORD, values); - if (rowId > 0) { - return true; - } - return false; - } - private int delete(String where, String[] whereArgs) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs); diff --git a/java/src/com/android/inputmethod/latin/ContactsDictionary.java b/java/src/com/android/inputmethod/latin/ContactsDictionary.java index f53ebf3f5..15edb706a 100644 --- a/java/src/com/android/inputmethod/latin/ContactsDictionary.java +++ b/java/src/com/android/inputmethod/latin/ContactsDictionary.java @@ -35,15 +35,8 @@ public class ContactsDictionary extends ExpandableDictionary { private ContentObserver mObserver; - private boolean mRequiresReload; - private long mLastLoadedContacts; - private boolean mUpdatingContacts; - - // Use this lock before touching mUpdatingContacts & mRequiresDownload - private Object mUpdatingLock = new Object(); - public ContactsDictionary(Context context) { super(context); // Perform a managed query. The Activity will handle closing and requerying the cursor @@ -53,15 +46,10 @@ public class ContactsDictionary extends ExpandableDictionary { cres.registerContentObserver(Contacts.CONTENT_URI, true, mObserver = new ContentObserver(null) { @Override public void onChange(boolean self) { - synchronized (mUpdatingLock) { - mRequiresReload = true; - } + setRequiresReload(true); } }); - - synchronized (mUpdatingLock) { - loadDictionaryAsyncLocked(); - } + loadDictionary(); } public synchronized void close() { @@ -69,41 +57,26 @@ public class ContactsDictionary extends ExpandableDictionary { getContext().getContentResolver().unregisterContentObserver(mObserver); mObserver = null; } + super.close(); } - private synchronized void loadDictionaryAsyncLocked() { + @Override + public void startDictionaryLoadingTaskLocked() { long now = SystemClock.uptimeMillis(); if (mLastLoadedContacts == 0 || now - mLastLoadedContacts > 30 * 60 * 1000 /* 30 minutes */) { - if (!mUpdatingContacts) { - mUpdatingContacts = true; - mRequiresReload = false; - new LoadContactsTask().execute(); - } + super.startDictionaryLoadingTaskLocked(); } } @Override - public synchronized void getWords(final WordComposer codes, final WordCallback callback, - int[] nextLettersFrequencies) { - synchronized (mUpdatingLock) { - // If we need to update, start off a background task - if (mRequiresReload) loadDictionaryAsyncLocked(); - // Currently updating contacts, don't return any results. - if (mUpdatingContacts) return; + public void loadDictionaryAsync() { + Cursor cursor = getContext().getContentResolver() + .query(Contacts.CONTENT_URI, PROJECTION, null, null, null); + if (cursor != null) { + addWords(cursor); } - super.getWords(codes, callback, nextLettersFrequencies); - } - - @Override - public synchronized boolean isValidWord(CharSequence word) { - synchronized (mUpdatingLock) { - // If we need to update, start off a background task - if (mRequiresReload) loadDictionaryAsyncLocked(); - if (mUpdatingContacts) return false; - } - - return super.isValidWord(word); + mLastLoadedContacts = SystemClock.uptimeMillis(); } private void addWords(Cursor cursor) { @@ -150,27 +123,5 @@ public class ContactsDictionary extends ExpandableDictionary { } cursor.close(); } - - private class LoadContactsTask extends AsyncTask { - @Override - protected Void doInBackground(Void... v) { - Cursor cursor = getContext().getContentResolver() - .query(Contacts.CONTENT_URI, PROJECTION, null, null, null); - if (cursor != null) { - addWords(cursor); - } - mLastLoadedContacts = SystemClock.uptimeMillis(); - return null; - } - @Override - protected void onPostExecute(Void result) { - // TODO Auto-generated method stub - synchronized (mUpdatingLock) { - mUpdatingContacts = false; - } - super.onPostExecute(result); - } - - } } diff --git a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java index 006593700..46bc41c42 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableDictionary.java @@ -16,7 +16,11 @@ package com.android.inputmethod.latin; +import com.android.inputmethod.latin.Dictionary.WordCallback; + import android.content.Context; +import android.os.AsyncTask; +import android.os.SystemClock; /** * Base class for an in-memory dictionary that can grow dynamically and can @@ -32,6 +36,13 @@ public class ExpandableDictionary extends Dictionary { public static final int MAX_WORD_LENGTH = 32; private static final char QUOTE = '\''; + private boolean mRequiresReload; + + private boolean mUpdatingDictionary; + + // Use this lock before touching mUpdatingDictionary & mRequiresDownload + private Object mUpdatingLock = new Object(); + static class Node { char code; int frequency; @@ -70,6 +81,34 @@ public class ExpandableDictionary extends Dictionary { mCodes = new int[MAX_WORD_LENGTH][]; } + public void loadDictionary() { + synchronized (mUpdatingLock) { + startDictionaryLoadingTaskLocked(); + } + } + + public void startDictionaryLoadingTaskLocked() { + if (!mUpdatingDictionary) { + mUpdatingDictionary = true; + mRequiresReload = false; + new LoadDictionaryTask().execute(); + } + } + + public void setRequiresReload(boolean reload) { + synchronized (mUpdatingLock) { + mRequiresReload = reload; + } + } + + public boolean getRequiresReload() { + return mRequiresReload; + } + + /** Override to load your dictionary here, on a background thread. */ + public void loadDictionaryAsync() { + } + Context getContext() { return mContext; } @@ -119,6 +158,13 @@ public class ExpandableDictionary extends Dictionary { @Override public void getWords(final WordComposer codes, final WordCallback callback, int[] nextLettersFrequencies) { + synchronized (mUpdatingLock) { + // If we need to update, start off a background task + if (mRequiresReload) startDictionaryLoadingTaskLocked(); + // Currently updating contacts, don't return any results. + if (mUpdatingDictionary) return; + } + mInputLength = codes.size(); mNextLettersFrequencies = nextLettersFrequencies; if (mCodes.length < mInputLength) mCodes = new int[mInputLength][]; @@ -135,6 +181,11 @@ public class ExpandableDictionary extends Dictionary { @Override public synchronized boolean isValidWord(CharSequence word) { + synchronized (mUpdatingLock) { + // If we need to update, start off a background task + if (mRequiresReload) startDictionaryLoadingTaskLocked(); + if (mUpdatingDictionary) return false; + } final int freq = getWordFrequencyRec(mRoots, word, 0, word.length()); return freq > -1; } @@ -277,6 +328,24 @@ public class ExpandableDictionary extends Dictionary { mRoots = new NodeArray(); } + private class LoadDictionaryTask extends AsyncTask { + @Override + protected Void doInBackground(Void... v) { + loadDictionaryAsync(); + return null; + } + + @Override + protected void onPostExecute(Void result) { + // TODO Auto-generated method stub + synchronized (mUpdatingLock) { + mUpdatingDictionary = false; + } + super.onPostExecute(result); + } + + } + static char toLowerCase(char c) { if (c < BASE_CHARS.length) { c = BASE_CHARS[c]; diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java index 4b98eacce..e8ca33af3 100644 --- a/java/src/com/android/inputmethod/latin/UserDictionary.java +++ b/java/src/com/android/inputmethod/latin/UserDictionary.java @@ -16,16 +16,11 @@ package com.android.inputmethod.latin; -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; -import android.net.Uri; import android.provider.UserDictionary.Words; public class UserDictionary extends ExpandableDictionary { @@ -40,8 +35,6 @@ public class UserDictionary extends ExpandableDictionary { private static final int INDEX_FREQUENCY = 2; private ContentObserver mObserver; - - private boolean mRequiresReload; private String mLocale; public UserDictionary(Context context, String locale) { @@ -54,26 +47,27 @@ public class UserDictionary extends ExpandableDictionary { cres.registerContentObserver(Words.CONTENT_URI, true, mObserver = new ContentObserver(null) { @Override public void onChange(boolean self) { - mRequiresReload = true; + setRequiresReload(true); } }); loadDictionary(); } - + public synchronized void close() { if (mObserver != null) { getContext().getContentResolver().unregisterContentObserver(mObserver); mObserver = null; } + super.close(); } - - private synchronized void loadDictionary() { + + @Override + public void loadDictionaryAsync() { Cursor cursor = getContext().getContentResolver() .query(Words.CONTENT_URI, PROJECTION, "(locale IS NULL) or (locale=?)", new String[] { mLocale }, null); addWords(cursor); - mRequiresReload = false; } /** @@ -86,7 +80,8 @@ public class UserDictionary extends ExpandableDictionary { */ @Override public synchronized void addWord(String word, int frequency) { - if (mRequiresReload) loadDictionary(); + // Force load the dictionary here synchronously + if (getRequiresReload()) loadDictionaryAsync(); // Safeguard against adding long words. Can cause stack overflow. if (word.length() >= getMaxWordLength()) return; @@ -101,19 +96,17 @@ public class UserDictionary extends ExpandableDictionary { getContext().getContentResolver().insert(Words.CONTENT_URI, values); // In case the above does a synchronous callback of the change observer - mRequiresReload = false; + setRequiresReload(false); } @Override public synchronized void getWords(final WordComposer codes, final WordCallback callback, int[] nextLettersFrequencies) { - if (mRequiresReload) loadDictionary(); super.getWords(codes, callback, nextLettersFrequencies); } @Override public synchronized boolean isValidWord(CharSequence word) { - if (mRequiresReload) loadDictionary(); return super.isValidWord(word); }