Write the auto dictionary data to disk in a background thread to avoid blocking the UI thread.

Bug: 2536846

This also potentially fixes the occasional hangs on pressing space. Need to verify.
Bug: 2509010
main
Amith Yamasani 2010-03-23 15:59:59 -07:00
parent bad436e93b
commit 4ff60be170
2 changed files with 72 additions and 27 deletions

View File

@ -17,6 +17,8 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import java.util.HashMap; import java.util.HashMap;
import java.util.Set;
import java.util.Map.Entry;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
@ -24,8 +26,8 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.os.AsyncTask;
import android.provider.BaseColumns; import android.provider.BaseColumns;
import android.provider.UserDictionary.Words;
import android.util.Log; import android.util.Log;
/** /**
@ -51,6 +53,9 @@ public class AutoDictionary extends ExpandableDictionary {
// Locale for which this auto dictionary is storing words // Locale for which this auto dictionary is storing words
private String mLocale; 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 String DATABASE_NAME = "auto_dict.db";
private static final int DATABASE_VERSION = 1; private static final int DATABASE_VERSION = 1;
@ -98,6 +103,7 @@ public class AutoDictionary extends ExpandableDictionary {
@Override @Override
public void close() { public void close() {
flushPendingWrites();
mOpenHelper.close(); mOpenHelper.close();
super.close(); super.close();
} }
@ -135,14 +141,29 @@ public class AutoDictionary extends ExpandableDictionary {
int freq = getWordFrequency(word); int freq = getWordFrequency(word);
freq = freq < 0 ? addFrequency : freq + addFrequency; freq = freq < 0 ? addFrequency : freq + addFrequency;
super.addWord(word, freq); super.addWord(word, freq);
if (freq >= PROMOTION_THRESHOLD) { if (freq >= PROMOTION_THRESHOLD) {
mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD); mIme.promoteToUserDictionary(word, FREQUENCY_FOR_AUTO_ADD);
// Delete the word (for input locale) from the auto dictionary db, as it freq = 0;
// is now in the user dictionary provider. }
delete(COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?",
new String[] { word, mLocale }); synchronized (mPendingWritesLock) {
} else { // Write a null frequency if it is to be deleted from the db
update(word, freq, mLocale); 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(), 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 +207,49 @@ public class AutoDictionary extends ExpandableDictionary {
return c; return c;
} }
private int delete(String where, String[] whereArgs) { /**
SQLiteDatabase db = mOpenHelper.getWritableDatabase(); * Async task to write pending words to the database so that it stays in sync with
int count = db.delete(AUTODICT_TABLE_NAME, where, whereArgs); * the in-memory trie.
return count; */
} 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) { public UpdateDbTask(Context context,
SQLiteDatabase db = mOpenHelper.getWritableDatabase(); HashMap<String, Integer> pendingWrites, String locale) {
long count = db.delete(AUTODICT_TABLE_NAME, COLUMN_WORD + "=? AND " + COLUMN_LOCALE + "=?", mMap = pendingWrites;
new String[] { word, locale }); mLocale = locale;
count = db.insert(AUTODICT_TABLE_NAME, null, mDbHelper = new DatabaseHelper(context);
getContentValues(word, frequency, locale)); }
return (int) count;
}
private ContentValues getContentValues(String word, int frequency, String locale) { @Override
ContentValues values = new ContentValues(4); protected Void doInBackground(Void... v) {
values.put(COLUMN_WORD, word); SQLiteDatabase db = mDbHelper.getWritableDatabase();
values.put(COLUMN_FREQUENCY, frequency); // Write all the entries to the db
values.put(COLUMN_LOCALE, locale); Set<Entry<String,Integer>> mEntries = mMap.entrySet();
return values; try {
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));
}
}
} finally {
mDbHelper.close();
}
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;
}
} }
} }

View File

@ -158,7 +158,7 @@ public class LatinIME extends InputMethodService
private UserDictionary mUserDictionary; private UserDictionary mUserDictionary;
private ContactsDictionary mContactsDictionary; private ContactsDictionary mContactsDictionary;
private ExpandableDictionary mAutoDictionary; private AutoDictionary mAutoDictionary;
private Hints mHints; private Hints mHints;
@ -562,6 +562,7 @@ public class LatinIME extends InputMethodService
if (mInputView != null) { if (mInputView != null) {
mInputView.closing(); mInputView.closing();
} }
if (mAutoDictionary != null) mAutoDictionary.flushPendingWrites();
} }
@Override @Override