diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/AutoDictionary.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/AutoDictionary.java | 130 |
1 files changed, 89 insertions, 41 deletions
diff --git a/java/src/com/android/inputmethod/latin/AutoDictionary.java b/java/src/com/android/inputmethod/latin/AutoDictionary.java index da9dd6eb9..93f1985ca 100644 --- a/java/src/com/android/inputmethod/latin/AutoDictionary.java +++ b/java/src/com/android/inputmethod/latin/AutoDictionary.java @@ -17,6 +17,8 @@ package com.android.inputmethod.latin; import java.util.HashMap; +import java.util.Set; +import java.util.Map.Entry; import android.content.ContentValues; import android.content.Context; @@ -24,8 +26,8 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; +import android.os.AsyncTask; import android.provider.BaseColumns; -import android.provider.UserDictionary.Words; import android.util.Log; /** @@ -51,6 +53,9 @@ public class AutoDictionary extends ExpandableDictionary { // Locale for which this auto dictionary is storing words private String mLocale; + private HashMap<String,Integer> mPendingWrites = new HashMap<String,Integer>(); + private final Object mPendingWritesLock = new Object(); + private static final String DATABASE_NAME = "auto_dict.db"; private static final int DATABASE_VERSION = 1; @@ -78,13 +83,15 @@ public class AutoDictionary extends ExpandableDictionary { sDictProjectionMap.put(COLUMN_LOCALE, COLUMN_LOCALE); } - private DatabaseHelper mOpenHelper; + private static DatabaseHelper mOpenHelper = null; public AutoDictionary(Context context, LatinIME ime, String locale) { super(context); mIme = ime; mLocale = locale; - mOpenHelper = new DatabaseHelper(getContext()); + if (mOpenHelper == null) { + mOpenHelper = new DatabaseHelper(getContext()); + } if (mLocale != null && mLocale.length() > 1) { loadDictionary(); } @@ -98,7 +105,11 @@ public class AutoDictionary extends ExpandableDictionary { @Override public void close() { - mOpenHelper.close(); + flushPendingWrites(); + // Don't close the database as locale changes will require it to be reopened anyway + // Also, the database is written to somewhat frequently, so it needs to be kept alive + // throughout the life of the process. + // mOpenHelper.close(); super.close(); } @@ -106,21 +117,24 @@ public class AutoDictionary extends ExpandableDictionary { public void loadDictionaryAsync() { // Load the words that correspond to the current input locale Cursor cursor = query(COLUMN_LOCALE + "=?", new String[] { mLocale }); - if (cursor.moveToFirst()) { - int wordIndex = cursor.getColumnIndex(COLUMN_WORD); - int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); - while (!cursor.isAfterLast()) { - String word = cursor.getString(wordIndex); - int frequency = cursor.getInt(frequencyIndex); - // Safeguard against adding really long words. Stack may overflow due - // to recursive lookup - if (word.length() < getMaxWordLength()) { - super.addWord(word, frequency); + try { + if (cursor.moveToFirst()) { + int wordIndex = cursor.getColumnIndex(COLUMN_WORD); + int frequencyIndex = cursor.getColumnIndex(COLUMN_FREQUENCY); + while (!cursor.isAfterLast()) { + String word = cursor.getString(wordIndex); + int frequency = cursor.getInt(frequencyIndex); + // Safeguard against adding really long words. Stack may overflow due + // to recursive lookup + if (word.length() < getMaxWordLength()) { + super.addWord(word, frequency); + } + cursor.moveToNext(); } - cursor.moveToNext(); } + } finally { + cursor.close(); } - cursor.close(); } @Override @@ -135,14 +149,29 @@ public class AutoDictionary extends ExpandableDictionary { int freq = getWordFrequency(word); freq = freq < 0 ? addFrequency : freq + addFrequency; super.addWord(word, freq); + if (freq >= PROMOTION_THRESHOLD) { mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); - // Delete the word (for input locale) from the auto dictionary db, as it - // is now in the user dictionary provider. - delete(COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", - new String[] { word, mLocale }); - } else { - update(word, freq, mLocale); + freq = 0; + } + + synchronized (mPendingWritesLock) { + // Write a null frequency if it is to be deleted from the db + mPendingWrites.put(word, freq == 0 ? null : new Integer(freq)); + } + } + + /** + * Schedules a background thread to write any pending words to the database. + */ + public void flushPendingWrites() { + synchronized (mPendingWritesLock) { + // Nothing pending? Return + if (mPendingWrites.isEmpty()) return; + // Create a background thread to write the pending entries + new UpdateDbTask(getContext(), mOpenHelper, mPendingWrites, mLocale).execute(); + // Create a new map for writing new entries into while the old one is written to db + mPendingWrites = new HashMap<String, Integer>(); } } @@ -186,26 +215,45 @@ public class AutoDictionary extends ExpandableDictionary { return c; } - private int delete(String where, String[] whereArgs) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs); - return count; - } + /** + * Async task to write pending words to the database so that it stays in sync with + * the in-memory trie. + */ + private static class UpdateDbTask extends AsyncTask<Void, Void, Void> { + private final HashMap<String, Integer> mMap; + private final DatabaseHelper mDbHelper; + private final String mLocale; - private int update(String word, int frequency, String locale) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - long count = db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", - new String[] { word, locale }); - count = db.insert(AUTODICT_TABLE_NAME, null, - getContentValues(word, frequency, locale)); - return (int) count; - } + public UpdateDbTask(Context context, DatabaseHelper openHelper, + HashMap<String, Integer> pendingWrites, String locale) { + mMap = pendingWrites; + mLocale = locale; + mDbHelper = openHelper; + } + + @Override + protected Void doInBackground(Void... v) { + SQLiteDatabase db = mDbHelper.getWritableDatabase(); + // Write all the entries to the db + Set<Entry<String,Integer>> mEntries = mMap.entrySet(); + for (Entry<String,Integer> entry : mEntries) { + Integer freq = entry.getValue(); + db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", + new String[] { entry.getKey(), mLocale }); + if (freq != null) { + db.insert(AUTODICT_TABLE_NAME, null, + getContentValues(entry.getKey(), freq, mLocale)); + } + } + return null; + } - private ContentValues getContentValues(String word, int frequency, String locale) { - ContentValues values = new ContentValues(4); - values.put(COLUMN_WORD, word); - values.put(COLUMN_FREQUENCY, frequency); - values.put(COLUMN_LOCALE, locale); - return values; + private ContentValues getContentValues(String word, int frequency, String locale) { + ContentValues values = new ContentValues(4); + values.put(COLUMN_WORD, word); + values.put(COLUMN_FREQUENCY, frequency); + values.put(COLUMN_LOCALE, locale); + return values; + } } } |