Permalink
Browse files

Issue #97: OOM fixes, there is a race-condition between the loading a…

…nd the closing, which caused the close to be irrelevent (loading was still in progress, so the close did nothing).
  • Loading branch information...
menny committed Feb 22, 2013
1 parent 2bf273d commit c2d74fff434ef9bd05d051a20d4b117b553928df
View
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.menny.android.anysoftkeyboard"
android:versionCode="95"
android:versionName="20130219-skinny-eye-candy" >
android:versionName="20130222-skinny-eye-candy" >
<supports-screens
android:anyDensity="true"
@@ -3378,13 +3378,12 @@ private void setDictionariesForCurrentKeyboard() {
String localeForSupportingDictionaries = dictionaryBuilder != null ? dictionaryBuilder
.getLanguage() : defaultDictionary;
mUserDictionary = mSuggest.getDictionaryFactory()
.createUserDictionary(this,
.createUserDictionary(getApplicationContext(),
localeForSupportingDictionaries);
mUserDictionary.loadDictionary();
mSuggest.setUserDictionary(mUserDictionary);
mAutoDictionary = mSuggest.getDictionaryFactory()
.createAutoDictionary(this, this,
.createAutoDictionary(getApplicationContext(), this,
localeForSupportingDictionaries);
mSuggest.setAutoDictionary(mAutoDictionary);
mSuggest.setContactsDictionary(getApplicationContext(),
@@ -40,41 +40,33 @@ public AndroidUserDictionary(Context context, String locale) {
mLocale = locale;
}
protected void closeAllResources() {
closeObserver();
}
private void closeObserver() {
protected synchronized void closeAllResources() {
if (mObserver != null) {
mContext.getContentResolver().unregisterContentObserver(mObserver);
mObserver = null;
}
}
@Override
public void loadDictionary() {
public synchronized void loadDictionary() {
// NOT doing it async, why? because my parent (SafeUserDictionary) is
// doing it async
loadDictionaryAsync();
}
protected void loadDictionaryAsync() {
protected synchronized void loadDictionaryAsync() {
WordsCursor cursor = getWordsCursor();
addWords(cursor.getCursor());
cursor.close();
// Perform a managed query. The Activity will handle closing and
// requerying the cursor
// when needed.
closeObserver();
ContentResolver cres = mContext.getContentResolver();
mObserver = new UserDictionaryContentObserver();
cres.registerContentObserver(Words.CONTENT_URI, true, mObserver);
}
public WordsCursor getWordsCursor() {
public synchronized WordsCursor getWordsCursor() {
Cursor cursor = TextUtils.isEmpty(mLocale) ? mContext
.getContentResolver().query(Words.CONTENT_URI, PROJECTION,
null, null, null) : mContext.getContentResolver()
@@ -138,7 +130,7 @@ protected void AddWordToStorage(String word, int frequency) {
}
@Override
public void deleteWord(String word) {
public synchronized void deleteWord(String word) {
mContext.getContentResolver().delete(Words.CONTENT_URI,
Words.WORD + "=?", new String[] { word });
reloadDictionary();
@@ -119,7 +119,7 @@ public boolean isValidWord(CharSequence word) {
}
@Override
public void close() {
public synchronized void close() {
flushPendingWrites();
// Don't close the database as locale changes will require it to be
// reopened anyway
@@ -131,7 +131,7 @@ public void close() {
}
@Override
protected void loadDictionaryAsync() {
protected synchronized void loadDictionaryAsync() {
// Load the words that correspond to the current input locale
WordsCursor wordsCursor = getWordsCursor();
Cursor cursor = wordsCursor.getCursor();
@@ -77,7 +77,7 @@ public boolean deliverSelfNotifications() {
}
@Override
protected void loadDictionaryAsync() {
protected synchronized void loadDictionaryAsync() {
Log.d(TAG, "Starting load of contact names...");
Cursor cursor = null;
try {
@@ -218,7 +218,7 @@ else if (timesContacted > 1)
}
@Override
protected void closeAllResources() {
protected synchronized void closeAllResources() {
if (mObserver != null) {
if (AnyApplication.DEBUG)
Log.d(TAG, "Unregisterring from contacts change notifications.");
@@ -228,15 +228,15 @@ protected void closeAllResources() {
}
@Override
protected void AddWordToStorage(String word, int frequency) {
protected synchronized void AddWordToStorage(String word, int frequency) {
}
@Override
public WordsCursor getWordsCursor() {
public synchronized WordsCursor getWordsCursor() {
return null;
}
@Override
public void deleteWord(String word) {
public synchronized void deleteWord(String word) {
}
}
@@ -22,7 +22,6 @@
import android.net.Uri;
import com.anysoftkeyboard.utils.Log;
import com.menny.android.anysoftkeyboard.AnyApplication;
@TargetApi(16)
public class ContactsDictionaryAPI16 extends ContactsDictionary {
@@ -6,61 +6,64 @@
import com.anysoftkeyboard.utils.Log;
import com.menny.android.anysoftkeyboard.AnyApplication;
public class DictionaryFactory
{
private static final String TAG = "ASK DictFctry";
private AutoDictionary mAutoDictionary = null;
private String mUserDictionaryLocale = null;
private EditableDictionary mUserDictionary = null;
public class DictionaryFactory {
private static final String TAG = "ASK DictFctry";
public DictionaryFactory()
{
}
public synchronized EditableDictionary createUserDictionary(Context context, String locale)
{
if (mUserDictionary != null && equalsString(mUserDictionaryLocale, locale)){
Log.d(TAG, "Returning cached user-dictionary for locale "+mUserDictionaryLocale);
return mUserDictionary;
}
Log.d(TAG, "Creating a new UserDictionart for locale "+locale);
mUserDictionary = new SafeUserDictionary(context, locale);
private AutoDictionary mAutoDictionary = null;
private String mUserDictionaryLocale = null;
private EditableDictionary mUserDictionary = null;
mUserDictionaryLocale = locale;
return mUserDictionary;
}
public synchronized EditableDictionary createContactsDictionary(Context context)
{
return null;
}
public boolean equalsString(String a, String b){
if(a == null && b == null){
return true;
}
if(a == null || b == null){
return false;
}
return a.equals(b);
}
public synchronized AutoDictionary createAutoDictionary(Context context, AnySoftKeyboard ime, String currentAutoDictionaryLocale)
{
if (AnyApplication.getConfig().getAutoDictionaryInsertionThreshold() < 0)
return null;
if (mAutoDictionary != null && equalsString(mAutoDictionary.getLocale(), currentAutoDictionaryLocale))
{
return mAutoDictionary;
}
Log.d(TAG, "Creating AutoDictionary for locale: "+currentAutoDictionaryLocale);
mAutoDictionary = new AutoDictionary(context, ime, currentAutoDictionaryLocale);
mAutoDictionary.loadDictionary();
return mAutoDictionary;
}
public DictionaryFactory() {
}
public synchronized EditableDictionary createUserDictionary(
Context context, String locale) {
if (mUserDictionary != null
&& equalsString(mUserDictionaryLocale, locale)) {
Log.d(TAG, "Returning cached user-dictionary for locale "
+ mUserDictionaryLocale);
return mUserDictionary;
}
Log.d(TAG, "Creating a new UserDictionart for locale " + locale);
mUserDictionary = new SafeUserDictionary(context, locale);
mUserDictionary.loadDictionary();
mUserDictionaryLocale = locale;
return mUserDictionary;
}
public synchronized EditableDictionary createContactsDictionary(
Context context) {
return null;
}
public boolean equalsString(String a, String b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.equals(b);
}
public synchronized AutoDictionary createAutoDictionary(Context context,
AnySoftKeyboard ime, String currentAutoDictionaryLocale) {
if (AnyApplication.getConfig().getAutoDictionaryInsertionThreshold() < 0)
return null;
if (mAutoDictionary != null
&& equalsString(mAutoDictionary.getLocale(),
currentAutoDictionaryLocale)) {
return mAutoDictionary;
}
Log.d(TAG, "Creating AutoDictionary for locale: "
+ currentAutoDictionaryLocale);
mAutoDictionary = new AutoDictionary(context, ime,
currentAutoDictionaryLocale);
mAutoDictionary.loadDictionary();
return mAutoDictionary;
}
}
@@ -17,7 +17,7 @@ protected DictionarySQLiteConnection createStorage() {
}
@Override
public void loadDictionary() {
public synchronized void loadDictionary() {
//NOT doing it async, why? because my parent (SafeUserDictionary) is doing it async
loadDictionaryAsync();
}
@@ -18,7 +18,7 @@ protected SQLiteUserDictionaryBase(String dictionaryName, Context context) {
}
@Override
protected void loadDictionaryAsync() {
protected synchronized void loadDictionaryAsync() {
try {
if (mStorage == null)
mStorage = createStorage();
@@ -60,7 +60,7 @@ protected void loadDictionaryAsync() {
}
@Override
public WordsCursor getWordsCursor() {
public synchronized WordsCursor getWordsCursor() {
Log.d(TAG, "getWordsCursor");
if (mStorage == null) {
Log.d(TAG, "getWordsCursor::createStorage");
@@ -72,18 +72,18 @@ public WordsCursor getWordsCursor() {
protected abstract DictionarySQLiteConnection createStorage();
@Override
protected void AddWordToStorage(String word, int frequency) {
protected synchronized void AddWordToStorage(String word, int frequency) {
mStorage.addWord(word, frequency);
}
@Override
public void deleteWord(String word) {
public synchronized void deleteWord(String word) {
mStorage.deleteWord(word);
reloadDictionary();
}
@Override
protected void closeAllResources() {
protected synchronized void closeAllResources() {
if (mStorage != null)
mStorage.close();
}
Oops, something went wrong.

0 comments on commit c2d74ff

Please sign in to comment.