diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 72d5435a8d31752197f31a2f8244921ace4ce747..67b57027718793677f5105c81a01444d81ada80f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -77,9 +77,7 @@ import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.ProductionFlag;
 import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever;
-import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
 import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister;
-import com.android.inputmethod.latin.personalization.PersonalizationHelper;
 import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
 import com.android.inputmethod.latin.settings.Settings;
 import com.android.inputmethod.latin.settings.SettingsActivity;
@@ -179,8 +177,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
 
     private boolean mIsMainDictionaryAvailable;
     private UserBinaryDictionary mUserDictionary;
-    private UserHistoryDictionary mUserHistoryDictionary;
-    private PersonalizationDictionary mPersonalizationDictionary;
     private boolean mIsUserDictionaryAvailable;
 
     private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
@@ -592,9 +588,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // the layout; at this time, we need to skip resetting the contacts dictionary. It will
         // be done later inside {@see #initSuggest()} when the reopenDictionaries message is
         // processed.
-        if (!mHandler.hasPendingReopenDictionaries()) {
-            // May need to reset the contacts dictionary depending on the user settings.
-            resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
+        if (!mHandler.hasPendingReopenDictionaries() && mSuggest != null) {
+            // May need to reset dictionaries depending on the user settings.
+            mSuggest.setAdditionalDictionaries(mSuggest /* oldSuggest */, mSettings.getCurrent());
         }
     }
 
@@ -640,63 +636,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         mUserDictionary = new UserBinaryDictionary(this, subtypeLocale);
         mIsUserDictionaryAvailable = mUserDictionary.isEnabled();
         newSuggest.setUserDictionary(mUserDictionary);
-
-        mUserHistoryDictionary = PersonalizationHelper.getUserHistoryDictionary(
-                this, subtypeLocale);
-        newSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
-        mPersonalizationDictionary =
-                PersonalizationHelper.getPersonalizationDictionary(this, subtypeLocale);
-        newSuggest.setPersonalizationDictionary(mPersonalizationDictionary);
-
+        newSuggest.setAdditionalDictionaries(mSuggest /* oldSuggest */, mSettings.getCurrent());
         final Suggest oldSuggest = mSuggest;
-        resetContactsDictionary(null != oldSuggest ? oldSuggest.getContactsDictionary() : null);
         mSuggest = newSuggest;
         if (oldSuggest != null) oldSuggest.close();
     }
 
-    /**
-     * Resets the contacts dictionary in mSuggest according to the user settings.
-     *
-     * This method takes an optional contacts dictionary to use when the locale hasn't changed
-     * since the contacts dictionary can be opened or closed as necessary depending on the settings.
-     *
-     * @param oldContactsDictionary an optional dictionary to use, or null
-     */
-    private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary) {
-        final Suggest suggest = mSuggest;
-        final boolean shouldSetDictionary =
-                (null != suggest && mSettings.getCurrent().mUseContactsDict);
-
-        final ContactsBinaryDictionary dictionaryToUse;
-        if (!shouldSetDictionary) {
-            // Make sure the dictionary is closed. If it is already closed, this is a no-op,
-            // so it's safe to call it anyways.
-            if (null != oldContactsDictionary) oldContactsDictionary.close();
-            dictionaryToUse = null;
-        } else {
-            final Locale locale = mSubtypeSwitcher.getCurrentSubtypeLocale();
-            if (null != oldContactsDictionary) {
-                if (!oldContactsDictionary.mLocale.equals(locale)) {
-                    // If the locale has changed then recreate the contacts dictionary. This
-                    // allows locale dependent rules for handling bigram name predictions.
-                    oldContactsDictionary.close();
-                    dictionaryToUse = new ContactsBinaryDictionary(this, locale);
-                } else {
-                    // Make sure the old contacts dictionary is opened. If it is already open,
-                    // this is a no-op, so it's safe to call it anyways.
-                    oldContactsDictionary.reopen(this);
-                    dictionaryToUse = oldContactsDictionary;
-                }
-            } else {
-                dictionaryToUse = new ContactsBinaryDictionary(this, locale);
-            }
-        }
-
-        if (null != suggest) {
-            suggest.setContactsDictionary(dictionaryToUse);
-        }
-    }
-
     /* package private */ void resetSuggestMainDict() {
         final Locale subtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
         mSuggest.resetMainDict(this, subtypeLocale, this /* SuggestInitializationListener */);
@@ -2861,7 +2806,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         final SettingsValues currentSettings = mSettings.getCurrent();
         if (!currentSettings.mCorrectionEnabled) return null;
 
-        final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
+        final UserHistoryDictionary userHistoryDictionary = suggest.getUserHistoryDictionary();
         if (userHistoryDictionary == null) return null;
 
         final String prevWord = mConnection.getNthPreviousWord(currentSettings, 2);
@@ -3076,7 +3021,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         }
         mConnection.deleteSurroundingText(deleteLength, 0);
         if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
-            mUserHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
+            if (mSuggest != null) {
+                mSuggest.cancelAddingUserHistory(previousWord, committedWord);
+            }
         }
         final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
         if (mSettings.getCurrent().mCurrentLanguageHasSpaces) {
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 0ecb41100ad0df5fd07c9dfa15f03bac2182c144..32ab1f3df2c18764885e9fa4bd2299999f5944ad 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -25,8 +25,10 @@ import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.ProximityInfo;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
+import com.android.inputmethod.latin.personalization.PersonalizationHelper;
 import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
 import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.latin.settings.SettingsValues;
 import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
 import com.android.inputmethod.latin.utils.BoundedTreeSet;
 import com.android.inputmethod.latin.utils.CollectionUtils;
@@ -71,7 +73,9 @@ public final class Suggest {
             CollectionUtils.newConcurrentHashMap();
     private HashSet<String> mOnlyDictionarySetForDebug = null;
     private Dictionary mMainDictionary;
-    private ContactsBinaryDictionary mContactsDict;
+    private ContactsBinaryDictionary mContactsDictionary;
+    private UserHistoryDictionary mUserHistoryDictionary;
+    private PersonalizationDictionary mPersonalizationDictionary;
     @UsedForTesting
     private boolean mIsCurrentlyWaitingForMainDictionary = false;
 
@@ -80,10 +84,14 @@ public final class Suggest {
     // Locale used for upper- and title-casing words
     public final Locale mLocale;
 
+    private final Context mContext;
+
     public Suggest(final Context context, final Locale locale,
             final SuggestInitializationListener listener) {
         initAsynchronously(context, locale, listener);
         mLocale = locale;
+        mContext = context;
+        // TODO: Use SettingsValues instead of Settings.
         // initialize a debug flag for the personalization
         if (Settings.readUseOnlyPersonalizationDictionaryForDebug(
                 PreferenceManager.getDefaultSharedPreferences(context))) {
@@ -93,10 +101,11 @@ public final class Suggest {
     }
 
     @UsedForTesting
-    Suggest(final AssetFileAddress[] dictionaryList, final Locale locale) {
+    Suggest(final Context context, final AssetFileAddress[] dictionaryList, final Locale locale) {
         final Dictionary mainDict = DictionaryFactory.createDictionaryForTest(dictionaryList,
                 false /* useFullEditDistance */, locale);
         mLocale = locale;
+        mContext = context;
         mMainDictionary = mainDict;
         addOrReplaceDictionaryInternal(Dictionary.TYPE_MAIN, mainDict);
     }
@@ -163,7 +172,15 @@ public final class Suggest {
     }
 
     public ContactsBinaryDictionary getContactsDictionary() {
-        return mContactsDict;
+        return mContactsDictionary;
+    }
+
+    public UserHistoryDictionary getUserHistoryDictionary() {
+        return mUserHistoryDictionary;
+    }
+
+    public PersonalizationDictionary getPersonalizationDictionary() {
+        return mPersonalizationDictionary;
     }
 
     public ConcurrentHashMap<String, Dictionary> getUnigramDictionaries() {
@@ -184,18 +201,120 @@ public final class Suggest {
      * won't be used.
      */
     public void setContactsDictionary(final ContactsBinaryDictionary contactsDictionary) {
-        mContactsDict = contactsDictionary;
+        mContactsDictionary = contactsDictionary;
         addOrReplaceDictionaryInternal(Dictionary.TYPE_CONTACTS, contactsDictionary);
     }
 
     public void setUserHistoryDictionary(final UserHistoryDictionary userHistoryDictionary) {
+        mUserHistoryDictionary = userHistoryDictionary;
         addOrReplaceDictionaryInternal(Dictionary.TYPE_USER_HISTORY, userHistoryDictionary);
     }
 
     public void setPersonalizationDictionary(
             final PersonalizationDictionary personalizationDictionary) {
-        addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION,
-                personalizationDictionary);
+        mPersonalizationDictionary = personalizationDictionary;
+        addOrReplaceDictionaryInternal(Dictionary.TYPE_PERSONALIZATION, personalizationDictionary);
+    }
+
+    /**
+     * Set dictionaries that can be turned off according to the user settings.
+     *
+     * @param oldSuggest the instance having old dictionaries
+     * @param settingsValues current SettingsValues
+     */
+    public void setAdditionalDictionaries(final Suggest oldSuggest,
+            final SettingsValues settingsValues) {
+        // Contacts dictionary
+        resetContactsDictionary(null != oldSuggest ? oldSuggest.getContactsDictionary() : null,
+                settingsValues);
+        // User history dictionary & Personalization dictionary
+        resetPersonalizedDictionaries(oldSuggest, settingsValues);
+    }
+
+    /**
+     * Set the user history dictionary and personalization dictionary according to the user
+     * settings.
+     *
+     * @param oldSuggest the instance that has been used
+     * @param settingsValues current settingsValues
+     */
+    // TODO: Consolidate resetPersonalizedDictionaries() and resetContactsDictionary(). Call up the
+    // new method for each dictionary.
+    private void resetPersonalizedDictionaries(final Suggest oldSuggest,
+            final SettingsValues settingsValues) {
+        final boolean shouldSetDictionaries = settingsValues.mUsePersonalizedDicts;
+
+        final UserHistoryDictionary oldUserHistoryDictionary = (null == oldSuggest) ? null :
+                oldSuggest.getUserHistoryDictionary();
+        final PersonalizationDictionary oldPersonalizationDictionary = (null == oldSuggest) ? null :
+                oldSuggest.getPersonalizationDictionary();
+        final UserHistoryDictionary userHistoryDictionaryToUse;
+        final PersonalizationDictionary personalizationDictionaryToUse;
+        if (!shouldSetDictionaries) {
+            userHistoryDictionaryToUse = null;
+            personalizationDictionaryToUse = null;
+        } else {
+            if (null != oldUserHistoryDictionary
+                    && oldUserHistoryDictionary.mLocale.equals(mLocale)) {
+                userHistoryDictionaryToUse = oldUserHistoryDictionary;
+            } else {
+                userHistoryDictionaryToUse =
+                        PersonalizationHelper.getUserHistoryDictionary(mContext, mLocale);
+            }
+            if (null != oldPersonalizationDictionary
+                    && oldPersonalizationDictionary.mLocale.equals(mLocale)) {
+                personalizationDictionaryToUse = oldPersonalizationDictionary;
+            } else {
+                personalizationDictionaryToUse =
+                        PersonalizationHelper.getPersonalizationDictionary(mContext, mLocale);
+            }
+        }
+        setUserHistoryDictionary(userHistoryDictionaryToUse);
+        setPersonalizationDictionary(personalizationDictionaryToUse);
+    }
+
+    /**
+     * Set the contacts dictionary according to the user settings.
+     *
+     * This method takes an optional contacts dictionary to use when the locale hasn't changed
+     * since the contacts dictionary can be opened or closed as necessary depending on the settings.
+     *
+     * @param oldContactsDictionary an optional dictionary to use, or null
+     * @param settingsValues current settingsValues
+     */
+    private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary,
+            final SettingsValues settingsValues) {
+        final boolean shouldSetDictionary = settingsValues.mUseContactsDict;
+        final ContactsBinaryDictionary dictionaryToUse;
+        if (!shouldSetDictionary) {
+            // Make sure the dictionary is closed. If it is already closed, this is a no-op,
+            // so it's safe to call it anyways.
+            if (null != oldContactsDictionary) oldContactsDictionary.close();
+            dictionaryToUse = null;
+        } else {
+            if (null != oldContactsDictionary) {
+                if (!oldContactsDictionary.mLocale.equals(mLocale)) {
+                    // If the locale has changed then recreate the contacts dictionary. This
+                    // allows locale dependent rules for handling bigram name predictions.
+                    oldContactsDictionary.close();
+                    dictionaryToUse = new ContactsBinaryDictionary(mContext, mLocale);
+                } else {
+                    // Make sure the old contacts dictionary is opened. If it is already open,
+                    // this is a no-op, so it's safe to call it anyways.
+                    oldContactsDictionary.reopen(mContext);
+                    dictionaryToUse = oldContactsDictionary;
+                }
+            } else {
+                dictionaryToUse = new ContactsBinaryDictionary(mContext, mLocale);
+            }
+        }
+        setContactsDictionary(dictionaryToUse);
+    }
+
+    public void cancelAddingUserHistory(final String previousWord, final String committedWord) {
+        if (mUserHistoryDictionary != null) {
+            mUserHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
+        }
     }
 
     public void setAutoCorrectionThreshold(float threshold) {
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 3a5c1155430063e34da71042e58439a7b7dd8d72..701c2902352cfe9204fd4c9bd83f1a9912d0ac1e 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -55,8 +55,8 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
 
     public static final int REQUIRED_BINARY_DICTIONARY_VERSION = FormatSpec.VERSION4;
 
-    /** Locale for which this user history dictionary is storing words */
-    private final Locale mLocale;
+    /** The locale for this dictionary. */
+    public final Locale mLocale;
 
     private final String mDictName;