Remove unnecessary onRefreshKeyboard call.

When using the sliding spacebar language switch on ICS, both
LatinIME.toggleLanguage() and
InputMethodService.onCurrentInputMethodSubtypeChanged() invoke
LatinIME.onRefreshKeyboard().  This change eliminates the first one if
it isn't necessary.

This change also cleans up the followings.
  * reuse theme Context when the keyboard theme hasn't been changed.
  * clear the Keyboard cache when theme has been switched.
  * eliminates unnecessary Context reference from LatinKeyboard and
    SlidingLocaleDrawable.
  * recycle Bitmap and reuse Canvas in KeyboardView.

Bug: 4725930
Change-Id: I87366e9304879d94d12b7345adea768d86d43519
This commit is contained in:
Tadashi G. Takaoka 2011-06-20 11:58:56 +09:00
parent e218baa6cc
commit 5a2d063047
6 changed files with 67 additions and 57 deletions

View file

@ -16,12 +16,12 @@
package com.android.inputmethod.compat; package com.android.inputmethod.compat;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.latin.SubtypeSwitcher;
import android.inputmethodservice.InputMethodService; import android.inputmethodservice.InputMethodService;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.deprecated.LanguageSwitcherProxy;
import com.android.inputmethod.latin.SubtypeSwitcher;
public class InputMethodServiceCompatWrapper extends InputMethodService { public class InputMethodServiceCompatWrapper extends InputMethodService {
// CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10 // CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED needs to be false if the API level is 10
// or previous. Note that InputMethodSubtype was added in the API level 11. // or previous. Note that InputMethodSubtype was added in the API level 11.

View file

@ -43,7 +43,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG; private static final boolean DEBUG_CACHE = LatinImeLogger.sDBG;
public static final boolean DEBUG_STATE = false; public static final boolean DEBUG_STATE = false;
private static String sConfigDefaultKeyboardThemeId;
public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902"; public static final String PREF_KEYBOARD_LAYOUT = "pref_keyboard_layout_20100902";
private static final int[] KEYBOARD_THEMES = { private static final int[] KEYBOARD_THEMES = {
R.style.KeyboardTheme, R.style.KeyboardTheme,
@ -102,7 +101,8 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
// Default is SETTINGS_KEY_MODE_AUTO. // Default is SETTINGS_KEY_MODE_AUTO.
private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO; private static final int DEFAULT_SETTINGS_KEY_MODE = SETTINGS_KEY_MODE_AUTO;
private int mThemeIndex; private int mThemeIndex = -1;
private Context mThemeContext;
private int mKeyboardWidth; private int mKeyboardWidth;
private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
@ -119,19 +119,32 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
sInstance.mInputMethodService = ims; sInstance.mInputMethodService = ims;
sInstance.mPrefs = prefs; sInstance.mPrefs = prefs;
sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance(); sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance();
sInstance.setContextThemeWrapper(ims, getKeyboardThemeIndex(ims, prefs));
try {
sConfigDefaultKeyboardThemeId = ims.getString(
R.string.config_default_keyboard_theme_id);
sInstance.mThemeIndex = Integer.valueOf(
prefs.getString(PREF_KEYBOARD_LAYOUT, sConfigDefaultKeyboardThemeId));
} catch (NumberFormatException e) {
sConfigDefaultKeyboardThemeId = "0";
sInstance.mThemeIndex = 0;
}
prefs.registerOnSharedPreferenceChangeListener(sInstance); prefs.registerOnSharedPreferenceChangeListener(sInstance);
} }
private static int getKeyboardThemeIndex(Context context, SharedPreferences prefs) {
final String defaultThemeId = context.getString(R.string.config_default_keyboard_theme_id);
final String themeId = prefs.getString(PREF_KEYBOARD_LAYOUT, defaultThemeId);
try {
final int themeIndex = Integer.valueOf(themeId);
if (themeIndex >= 0 && themeIndex < KEYBOARD_THEMES.length)
return themeIndex;
} catch (NumberFormatException e) {
// Format error, keyboard theme is default to 0.
}
Log.w(TAG, "Illegal keyboard theme in preference: " + themeId + ", default to 0");
return 0;
}
private void setContextThemeWrapper(Context context, int themeIndex) {
if (mThemeIndex != themeIndex) {
mThemeIndex = themeIndex;
mThemeContext = new ContextThemeWrapper(context, KEYBOARD_THEMES[themeIndex]);
mKeyboardCache.clear();
}
}
public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled, public void loadKeyboard(EditorInfo attribute, boolean voiceKeyEnabled,
boolean voiceButtonOnPrimary) { boolean voiceButtonOnPrimary) {
mSwitchState = SWITCH_STATE_ALPHA; mSwitchState = SWITCH_STATE_ALPHA;
@ -202,9 +215,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
final Locale savedLocale = Utils.setSystemLocale(res, final Locale savedLocale = Utils.setSystemLocale(res,
mSubtypeSwitcher.getInputLocale()); mSubtypeSwitcher.getInputLocale());
final Context themeContext = new ContextThemeWrapper(mInputMethodService, keyboard = new LatinKeyboard(mThemeContext, id, id.mWidth);
KEYBOARD_THEMES[mThemeIndex]);
keyboard = new LatinKeyboard(themeContext, id, id.mWidth);
if (id.mEnableShiftLock) { if (id.mEnableShiftLock) {
keyboard.enableShiftLock(); keyboard.enableShiftLock();
@ -724,30 +735,29 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (mKeyboardView != null) { if (mKeyboardView != null) {
mKeyboardView.closing(); mKeyboardView.closing();
} }
final int themeIndex = (newThemeIndex < KEYBOARD_THEMES.length) ? newThemeIndex
: Integer.valueOf(sConfigDefaultKeyboardThemeId);
final int oldThemeIndex = mThemeIndex;
Utils.GCUtils.getInstance().reset(); Utils.GCUtils.getInstance().reset();
boolean tryGC = true; boolean tryGC = true;
for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) { for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
try { try {
final Context themeContext = new ContextThemeWrapper(mInputMethodService, setContextThemeWrapper(mInputMethodService, newThemeIndex);
KEYBOARD_THEMES[themeIndex]); mCurrentInputView = LayoutInflater.from(mThemeContext).inflate(
mCurrentInputView = LayoutInflater.from(themeContext).inflate(
R.layout.input_view, null); R.layout.input_view, null);
tryGC = false; tryGC = false;
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
Log.w(TAG, "load keyboard failed: " + e); Log.w(TAG, "load keyboard failed: " + e);
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
oldThemeIndex + "," + newThemeIndex, e);
} catch (InflateException e) { } catch (InflateException e) {
Log.w(TAG, "load keyboard failed: " + e); Log.w(TAG, "load keyboard failed: " + e);
tryGC = Utils.GCUtils.getInstance().tryGCOrWait(mThemeIndex + "," + themeIndex, e); tryGC = Utils.GCUtils.getInstance().tryGCOrWait(
oldThemeIndex + "," + newThemeIndex, e);
} }
} }
mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
mKeyboardView.setOnKeyboardActionListener(mInputMethodService); mKeyboardView.setOnKeyboardActionListener(mInputMethodService);
mThemeIndex = themeIndex;
return mCurrentInputView; return mCurrentInputView;
} }
@ -766,8 +776,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (PREF_KEYBOARD_LAYOUT.equals(key)) { if (PREF_KEYBOARD_LAYOUT.equals(key)) {
final int layoutId = Integer.valueOf( final int layoutId = getKeyboardThemeIndex(mInputMethodService, sharedPreferences);
sharedPreferences.getString(key, sConfigDefaultKeyboardThemeId));
postSetInputView(createInputView(layoutId, false)); postSetInputView(createInputView(layoutId, false));
} else if (Settings.PREF_SETTINGS_KEY.equals(key)) { } else if (Settings.PREF_SETTINGS_KEY.equals(key)) {
mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences, mSettingsKeyEnabledInSettings = getSettingsKeyMode(sharedPreferences,

View file

@ -626,9 +626,15 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
mDirtyRect.union(0, 0, width, height); mDirtyRect.union(0, 0, width, height);
} }
if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) { if (mBuffer == null || mBuffer.getWidth() != width || mBuffer.getHeight() != height) {
if (mBuffer != null)
mBuffer.recycle();
mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mBuffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
if (mCanvas != null) {
mCanvas.setBitmap(mBuffer);
} else {
mCanvas = new Canvas(mBuffer); mCanvas = new Canvas(mBuffer);
} }
}
final Canvas canvas = mCanvas; final Canvas canvas = mCanvas;
canvas.clipRect(mDirtyRect, Op.REPLACE); canvas.clipRect(mDirtyRect, Op.REPLACE);
canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR); canvas.drawColor(Color.BLACK, PorterDuff.Mode.CLEAR);

View file

@ -16,9 +16,6 @@
package com.android.inputmethod.keyboard; package com.android.inputmethod.keyboard;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.Resources.Theme; import android.content.res.Resources.Theme;
@ -36,6 +33,9 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
import java.lang.ref.SoftReference; import java.lang.ref.SoftReference;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -49,7 +49,8 @@ public class LatinKeyboard extends Keyboard {
public static final int CODE_NEXT_LANGUAGE = -100; public static final int CODE_NEXT_LANGUAGE = -100;
public static final int CODE_PREV_LANGUAGE = -101; public static final int CODE_PREV_LANGUAGE = -101;
private final Context mContext; private final Resources mRes;
private final Theme mTheme;
private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance(); private final SubtypeSwitcher mSubtypeSwitcher = SubtypeSwitcher.getInstance();
/* Space key and its icons, drawables and colors. */ /* Space key and its icons, drawables and colors. */
@ -65,7 +66,7 @@ public class LatinKeyboard extends Keyboard {
private float mSpacebarTextFadeFactor = 0.0f; private float mSpacebarTextFadeFactor = 0.0f;
private final int mSpacebarLanguageSwitchThreshold; private final int mSpacebarLanguageSwitchThreshold;
private int mSpacebarSlidingLanguageSwitchDiff; private int mSpacebarSlidingLanguageSwitchDiff;
private SlidingLocaleDrawable mSlidingLocaleIcon; private final SlidingLocaleDrawable mSlidingLocaleIcon;
private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache = private final HashMap<Integer, SoftReference<BitmapDrawable>> mSpaceDrawableCache =
new HashMap<Integer, SoftReference<BitmapDrawable>>(); new HashMap<Integer, SoftReference<BitmapDrawable>>();
@ -90,7 +91,8 @@ public class LatinKeyboard extends Keyboard {
public LatinKeyboard(Context context, KeyboardId id, int width) { public LatinKeyboard(Context context, KeyboardId id, int width) {
super(context, id.getXmlId(), id, width); super(context, id.getXmlId(), id, width);
mContext = context; mRes = context.getResources();
mTheme = context.getTheme();
final List<Key> keys = getKeys(); final List<Key> keys = getKeys();
int spaceKeyIndex = -1; int spaceKeyIndex = -1;
@ -133,6 +135,13 @@ public class LatinKeyboard extends Keyboard {
// The threshold is "key width" x 1.25 // The threshold is "key width" x 1.25
mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4; mSpacebarLanguageSwitchThreshold = (getMostCommonKeyWidth() * 5) / 4;
final int spaceKeyWidth = Math.max(mSpaceKey.mWidth,
(int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
final int spaceKeyheight = mSpacePreviewIcon.getIntrinsicHeight();
mSlidingLocaleIcon = new SlidingLocaleDrawable(
context, mSpacePreviewIcon, spaceKeyWidth, spaceKeyheight);
mSlidingLocaleIcon.setBounds(0, 0, spaceKeyWidth, spaceKeyheight);
} }
public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) { public void setSpacebarTextFadeFactor(float fadeFactor, LatinKeyboardView view) {
@ -250,7 +259,7 @@ public class LatinKeyboard extends Keyboard {
final SoftReference<BitmapDrawable> ref = mSpaceDrawableCache.get(hashCode); final SoftReference<BitmapDrawable> ref = mSpaceDrawableCache.get(hashCode);
BitmapDrawable drawable = (ref == null) ? null : ref.get(); BitmapDrawable drawable = (ref == null) ? null : ref.get();
if (drawable == null) { if (drawable == null) {
drawable = new BitmapDrawable(mContext.getResources(), drawSpacebar( drawable = new BitmapDrawable(mRes, drawSpacebar(
locale, isAutoCorrection, mSpacebarTextFadeFactor)); locale, isAutoCorrection, mSpacebarTextFadeFactor));
mSpaceDrawableCache.put(hashCode, new SoftReference<BitmapDrawable>(drawable)); mSpaceDrawableCache.put(hashCode, new SoftReference<BitmapDrawable>(drawable));
} }
@ -263,7 +272,7 @@ public class LatinKeyboard extends Keyboard {
final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight; final int height = mSpaceIcon != null ? mSpaceIcon.getIntrinsicHeight() : mSpaceKey.mHeight;
final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); final Bitmap buffer = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(buffer); final Canvas canvas = new Canvas(buffer);
final Resources res = mContext.getResources(); final Resources res = mRes;
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
// If application locales are explicitly selected. // If application locales are explicitly selected.
@ -287,7 +296,7 @@ public class LatinKeyboard extends Keyboard {
final String language = layoutSpacebar(paint, inputLocale, final String language = layoutSpacebar(paint, inputLocale,
mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height, mSpacebarArrowLeftIcon, mSpacebarArrowRightIcon, width, height,
getTextSizeFromTheme(mContext.getTheme(), textStyle, defaultTextSize)); getTextSizeFromTheme(mTheme, textStyle, defaultTextSize));
// Draw language text with shadow // Draw language text with shadow
// In case there is no space icon, we will place the language text at the center of // In case there is no space icon, we will place the language text at the center of
@ -341,14 +350,6 @@ public class LatinKeyboard extends Keyboard {
if (mSpacebarSlidingLanguageSwitchDiff == diff) if (mSpacebarSlidingLanguageSwitchDiff == diff)
return; return;
mSpacebarSlidingLanguageSwitchDiff = diff; mSpacebarSlidingLanguageSwitchDiff = diff;
if (mSlidingLocaleIcon == null) {
final int width = Math.max(mSpaceKey.mWidth,
(int)(getMinWidth() * SPACEBAR_POPUP_MIN_RATIO));
final int height = mSpacePreviewIcon.getIntrinsicHeight();
mSlidingLocaleIcon =
new SlidingLocaleDrawable(mContext, mSpacePreviewIcon, width, height);
mSlidingLocaleIcon.setBounds(0, 0, width, height);
}
mSlidingLocaleIcon.setDiff(diff); mSlidingLocaleIcon.setDiff(diff);
if (Math.abs(diff) == Integer.MAX_VALUE) { if (Math.abs(diff) == Integer.MAX_VALUE) {
mSpaceKey.setPreviewIcon(mSpacePreviewIcon); mSpaceKey.setPreviewIcon(mSpacePreviewIcon);
@ -403,7 +404,7 @@ public class LatinKeyboard extends Keyboard {
Math.max(0, Math.min(y, getHeight() - 1))); Math.max(0, Math.min(y, getHeight() - 1)));
} }
private static int getTextSizeFromTheme(Theme theme, int style, int defValue) { public static int getTextSizeFromTheme(Theme theme, int style, int defValue) {
TypedArray array = theme.obtainStyledAttributes( TypedArray array = theme.obtainStyledAttributes(
style, new int[] { android.R.attr.textSize }); style, new int[] { android.R.attr.textSize });
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue); int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);

View file

@ -60,8 +60,8 @@ public class SlidingLocaleDrawable extends Drawable {
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
final TextPaint textPaint = new TextPaint(); final TextPaint textPaint = new TextPaint();
textPaint.setTextSize(getTextSizeFromTheme( textPaint.setTextSize(LatinKeyboard.getTextSizeFromTheme(
context, android.R.style.TextAppearance_Medium, 18)); context.getTheme(), android.R.style.TextAppearance_Medium, 18));
textPaint.setColor(Color.TRANSPARENT); textPaint.setColor(Color.TRANSPARENT);
textPaint.setTextAlign(Align.CENTER); textPaint.setTextAlign(Align.CENTER);
textPaint.setAntiAlias(true); textPaint.setAntiAlias(true);
@ -78,13 +78,6 @@ public class SlidingLocaleDrawable extends Drawable {
mThreshold = ViewConfiguration.get(context).getScaledTouchSlop(); mThreshold = ViewConfiguration.get(context).getScaledTouchSlop();
} }
private static int getTextSizeFromTheme(Context context, int style, int defValue) {
TypedArray array = context.getTheme().obtainStyledAttributes(
style, new int[] { android.R.attr.textSize });
int textSize = array.getDimensionPixelSize(array.getResourceId(0, 0), defValue);
return textSize;
}
void setDiff(int diff) { void setDiff(int diff) {
if (diff == Integer.MAX_VALUE) { if (diff == Integer.MAX_VALUE) {
mHitThreshold = false; mHitThreshold = false;

View file

@ -1871,6 +1871,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} }
// The following is necessary because on API levels < 10, we don't get notified when // The following is necessary because on API levels < 10, we don't get notified when
// subtype changes. // subtype changes.
if (!CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED)
onRefreshKeyboard(); onRefreshKeyboard();
} }