Avoid memory leak by by non-static Handler inner classes
bug: 4901934 Change-Id: I870ab2e621ef3640a84468f09c074cdd726dc963main
parent
e7de39ac42
commit
4f0d290c5d
|
@ -18,7 +18,6 @@ package com.android.inputmethod.accessibility;
|
|||
|
||||
import android.content.SharedPreferences;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
|
@ -26,6 +25,7 @@ import android.view.inputmethod.ExtractedText;
|
|||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
|
||||
import com.android.inputmethod.latin.R;
|
||||
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
|
||||
|
||||
public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActionListener {
|
||||
private static final AccessibleInputMethodServiceProxy sInstance =
|
||||
|
@ -42,18 +42,20 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
|
|||
|
||||
private AccessibilityHandler mAccessibilityHandler;
|
||||
|
||||
private class AccessibilityHandler extends Handler {
|
||||
private static class AccessibilityHandler
|
||||
extends StaticInnerHandlerWrapper<AccessibleInputMethodServiceProxy> {
|
||||
private static final int MSG_NO_HOVER_SELECTION = 0;
|
||||
|
||||
public AccessibilityHandler(Looper looper) {
|
||||
super(looper);
|
||||
public AccessibilityHandler(AccessibleInputMethodServiceProxy outerInstance,
|
||||
Looper looper) {
|
||||
super(outerInstance, looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_NO_HOVER_SELECTION:
|
||||
notifyNoHoverSelection();
|
||||
getOuterInstance().notifyNoHoverSelection();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +84,7 @@ public class AccessibleInputMethodServiceProxy implements AccessibleKeyboardActi
|
|||
|
||||
private void initInternal(InputMethodService inputMethod, SharedPreferences prefs) {
|
||||
mInputMethod = inputMethod;
|
||||
mAccessibilityHandler = new AccessibilityHandler(inputMethod.getMainLooper());
|
||||
mAccessibilityHandler = new AccessibilityHandler(this, inputMethod.getMainLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -19,6 +19,7 @@ package com.android.inputmethod.deprecated.voice;
|
|||
import com.android.inputmethod.latin.EditingUtils;
|
||||
import com.android.inputmethod.latin.LatinImeLogger;
|
||||
import com.android.inputmethod.latin.R;
|
||||
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
|
@ -26,7 +27,6 @@ import android.content.Intent;
|
|||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.speech.RecognitionListener;
|
||||
|
@ -132,13 +132,20 @@ public class VoiceInput implements OnClickListener {
|
|||
|
||||
private final static int MSG_RESET = 1;
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
private final UIHandler mHandler = new UIHandler(this);
|
||||
|
||||
private static class UIHandler extends StaticInnerHandlerWrapper<VoiceInput> {
|
||||
public UIHandler(VoiceInput outerInstance) {
|
||||
super(outerInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
if (msg.what == MSG_RESET) {
|
||||
mState = DEFAULT;
|
||||
mRecognitionView.finish();
|
||||
mUiListener.onCancelVoice();
|
||||
final VoiceInput voiceInput = getOuterInstance();
|
||||
voiceInput.mState = DEFAULT;
|
||||
voiceInput.mRecognitionView.finish();
|
||||
voiceInput.mUiListener.onCancelVoice();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@ import android.graphics.Rect;
|
|||
import android.graphics.Region.Op;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
@ -53,6 +52,7 @@ import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
|
|||
import com.android.inputmethod.keyboard.internal.SwipeTracker;
|
||||
import com.android.inputmethod.latin.LatinImeLogger;
|
||||
import com.android.inputmethod.latin.R;
|
||||
import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -193,9 +193,9 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
private static final String KEY_LABEL_REFERENCE_CHAR = "M";
|
||||
private final int mKeyLabelHorizontalPadding;
|
||||
|
||||
private final UIHandler mHandler = new UIHandler();
|
||||
private final UIHandler mHandler = new UIHandler(this);
|
||||
|
||||
class UIHandler extends Handler {
|
||||
public static class UIHandler extends StaticInnerHandlerWrapper<KeyboardView> {
|
||||
private static final int MSG_SHOW_KEY_PREVIEW = 1;
|
||||
private static final int MSG_DISMISS_KEY_PREVIEW = 2;
|
||||
private static final int MSG_REPEAT_KEY = 3;
|
||||
|
@ -205,34 +205,40 @@ public class KeyboardView extends View implements PointerTracker.UIProxy {
|
|||
|
||||
private boolean mInKeyRepeat;
|
||||
|
||||
public UIHandler(KeyboardView outerInstance) {
|
||||
super(outerInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final KeyboardView keyboardView = getOuterInstance();
|
||||
final PointerTracker tracker = (PointerTracker) msg.obj;
|
||||
switch (msg.what) {
|
||||
case MSG_SHOW_KEY_PREVIEW:
|
||||
showKey(msg.arg1, tracker);
|
||||
keyboardView.showKey(msg.arg1, tracker);
|
||||
break;
|
||||
case MSG_DISMISS_KEY_PREVIEW:
|
||||
mPreviewText.setVisibility(View.INVISIBLE);
|
||||
keyboardView.mPreviewText.setVisibility(View.INVISIBLE);
|
||||
break;
|
||||
case MSG_REPEAT_KEY:
|
||||
tracker.onRepeatKey(msg.arg1);
|
||||
startKeyRepeatTimer(mKeyRepeatInterval, msg.arg1, tracker);
|
||||
startKeyRepeatTimer(keyboardView.mKeyRepeatInterval, msg.arg1, tracker);
|
||||
break;
|
||||
case MSG_LONGPRESS_KEY:
|
||||
openMiniKeyboardIfRequired(msg.arg1, tracker);
|
||||
keyboardView.openMiniKeyboardIfRequired(msg.arg1, tracker);
|
||||
break;
|
||||
case MSG_LONGPRESS_SHIFT_KEY:
|
||||
onLongPressShiftKey(tracker);
|
||||
keyboardView.onLongPressShiftKey(tracker);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void showKeyPreview(long delay, int keyIndex, PointerTracker tracker) {
|
||||
final KeyboardView keyboardView = getOuterInstance();
|
||||
removeMessages(MSG_SHOW_KEY_PREVIEW);
|
||||
if (mPreviewText.getVisibility() == VISIBLE || delay == 0) {
|
||||
if (keyboardView.mPreviewText.getVisibility() == VISIBLE || delay == 0) {
|
||||
// Show right away, if it's already visible and finger is moving around
|
||||
showKey(keyIndex, tracker);
|
||||
keyboardView.showKey(keyIndex, tracker);
|
||||
} else {
|
||||
sendMessageDelayed(
|
||||
obtainMessage(MSG_SHOW_KEY_PREVIEW, keyIndex, 0, tracker), delay);
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.content.res.Resources;
|
|||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
|
@ -95,23 +94,28 @@ public class CandidateView extends LinearLayout implements OnClickListener, OnLo
|
|||
private boolean mShowingAutoCorrectionInverted;
|
||||
private boolean mShowingAddToDictionary;
|
||||
|
||||
private final UiHandler mHandler = new UiHandler();
|
||||
private final UiHandler mHandler = new UiHandler(this);
|
||||
|
||||
private class UiHandler extends Handler {
|
||||
private static class UiHandler extends StaticInnerHandlerWrapper<CandidateView> {
|
||||
private static final int MSG_HIDE_PREVIEW = 0;
|
||||
private static final int MSG_UPDATE_SUGGESTION = 1;
|
||||
|
||||
private static final long DELAY_HIDE_PREVIEW = 1000;
|
||||
private static final long DELAY_UPDATE_SUGGESTION = 300;
|
||||
|
||||
public UiHandler(CandidateView outerInstance) {
|
||||
super(outerInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchMessage(Message msg) {
|
||||
final CandidateView candidateView = getOuterInstance();
|
||||
switch (msg.what) {
|
||||
case MSG_HIDE_PREVIEW:
|
||||
hidePreview();
|
||||
candidateView.hidePreview();
|
||||
break;
|
||||
case MSG_UPDATE_SUGGESTION:
|
||||
updateSuggestions();
|
||||
candidateView.updateSuggestions();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import android.inputmethodservice.InputMethodService;
|
|||
import android.media.AudioManager;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
|
@ -206,9 +205,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
private CharSequence mEnteredText;
|
||||
|
||||
|
||||
public final UIHandler mHandler = new UIHandler();
|
||||
public final UIHandler mHandler = new UIHandler(this);
|
||||
|
||||
public class UIHandler extends Handler {
|
||||
public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
|
||||
private static final int MSG_UPDATE_SUGGESTIONS = 0;
|
||||
private static final int MSG_UPDATE_OLD_SUGGESTIONS = 1;
|
||||
private static final int MSG_UPDATE_SHIFT_STATE = 2;
|
||||
|
@ -218,42 +217,50 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
private static final int MSG_SPACE_TYPED = 6;
|
||||
private static final int MSG_SET_BIGRAM_PREDICTIONS = 7;
|
||||
|
||||
public UIHandler(LatinIME outerInstance) {
|
||||
super(outerInstance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
final LatinIME latinIme = getOuterInstance();
|
||||
final KeyboardSwitcher switcher = latinIme.mKeyboardSwitcher;
|
||||
final LatinKeyboardView inputView = switcher.getKeyboardView();
|
||||
switch (msg.what) {
|
||||
case MSG_UPDATE_SUGGESTIONS:
|
||||
updateSuggestions();
|
||||
latinIme.updateSuggestions();
|
||||
break;
|
||||
case MSG_UPDATE_OLD_SUGGESTIONS:
|
||||
mRecorrection.fetchAndDisplayRecorrectionSuggestions(mVoiceProxy, mCandidateView,
|
||||
mSuggest, mKeyboardSwitcher, mWord, mHasUncommittedTypedChars,
|
||||
mLastSelectionStart, mLastSelectionEnd, mSettingsValues.mWordSeparators);
|
||||
latinIme.mRecorrection.fetchAndDisplayRecorrectionSuggestions(
|
||||
latinIme.mVoiceProxy, latinIme.mCandidateView,
|
||||
latinIme.mSuggest, latinIme.mKeyboardSwitcher, latinIme.mWord,
|
||||
latinIme.mHasUncommittedTypedChars, latinIme.mLastSelectionStart,
|
||||
latinIme.mLastSelectionEnd, latinIme.mSettingsValues.mWordSeparators);
|
||||
break;
|
||||
case MSG_UPDATE_SHIFT_STATE:
|
||||
switcher.updateShiftState();
|
||||
break;
|
||||
case MSG_SET_BIGRAM_PREDICTIONS:
|
||||
updateBigramPredictions();
|
||||
latinIme.updateBigramPredictions();
|
||||
break;
|
||||
case MSG_VOICE_RESULTS:
|
||||
mVoiceProxy.handleVoiceResults(preferCapitalization()
|
||||
latinIme.mVoiceProxy.handleVoiceResults(latinIme.preferCapitalization()
|
||||
|| (switcher.isAlphabetMode() && switcher.isShiftedOrShiftLocked()));
|
||||
break;
|
||||
case MSG_FADEOUT_LANGUAGE_ON_SPACEBAR:
|
||||
if (inputView != null) {
|
||||
inputView.setSpacebarTextFadeFactor(
|
||||
(1.0f + mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
|
||||
(1.0f + latinIme.mSettingsValues.
|
||||
mFinalFadeoutFactorOfLanguageOnSpacebar) / 2,
|
||||
(LatinKeyboard)msg.obj);
|
||||
}
|
||||
sendMessageDelayed(obtainMessage(MSG_DISMISS_LANGUAGE_ON_SPACEBAR, msg.obj),
|
||||
mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
|
||||
latinIme.mSettingsValues.mDurationOfFadeoutLanguageOnSpacebar);
|
||||
break;
|
||||
case MSG_DISMISS_LANGUAGE_ON_SPACEBAR:
|
||||
if (inputView != null) {
|
||||
inputView.setSpacebarTextFadeFactor(
|
||||
mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
|
||||
latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
|
||||
(LatinKeyboard)msg.obj);
|
||||
}
|
||||
break;
|
||||
|
@ -263,7 +270,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
public void postUpdateSuggestions() {
|
||||
removeMessages(MSG_UPDATE_SUGGESTIONS);
|
||||
sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS),
|
||||
mSettingsValues.mDelayUpdateSuggestions);
|
||||
getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
|
||||
}
|
||||
|
||||
public void cancelUpdateSuggestions() {
|
||||
|
@ -277,7 +284,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
public void postUpdateOldSuggestions() {
|
||||
removeMessages(MSG_UPDATE_OLD_SUGGESTIONS);
|
||||
sendMessageDelayed(obtainMessage(MSG_UPDATE_OLD_SUGGESTIONS),
|
||||
mSettingsValues.mDelayUpdateOldSuggestions);
|
||||
getOuterInstance().mSettingsValues.mDelayUpdateOldSuggestions);
|
||||
}
|
||||
|
||||
public void cancelUpdateOldSuggestions() {
|
||||
|
@ -287,7 +294,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
public void postUpdateShiftKeyState() {
|
||||
removeMessages(MSG_UPDATE_SHIFT_STATE);
|
||||
sendMessageDelayed(obtainMessage(MSG_UPDATE_SHIFT_STATE),
|
||||
mSettingsValues.mDelayUpdateShiftState);
|
||||
getOuterInstance().mSettingsValues.mDelayUpdateShiftState);
|
||||
}
|
||||
|
||||
public void cancelUpdateShiftState() {
|
||||
|
@ -297,7 +304,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
public void postUpdateBigramPredictions() {
|
||||
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
|
||||
sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS),
|
||||
mSettingsValues.mDelayUpdateSuggestions);
|
||||
getOuterInstance().mSettingsValues.mDelayUpdateSuggestions);
|
||||
}
|
||||
|
||||
public void cancelUpdateBigramPredictions() {
|
||||
|
@ -309,23 +316,26 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
}
|
||||
|
||||
public void startDisplayLanguageOnSpacebar(boolean localeChanged) {
|
||||
final LatinIME latinIme = getOuterInstance();
|
||||
removeMessages(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR);
|
||||
removeMessages(MSG_DISMISS_LANGUAGE_ON_SPACEBAR);
|
||||
final LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
|
||||
final LatinKeyboardView inputView = latinIme.mKeyboardSwitcher.getKeyboardView();
|
||||
if (inputView != null) {
|
||||
final LatinKeyboard keyboard = mKeyboardSwitcher.getLatinKeyboard();
|
||||
final LatinKeyboard keyboard = latinIme.mKeyboardSwitcher.getLatinKeyboard();
|
||||
// The language is always displayed when the delay is negative.
|
||||
final boolean needsToDisplayLanguage = localeChanged
|
||||
|| mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
|
||||
|| latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar < 0;
|
||||
// The language is never displayed when the delay is zero.
|
||||
if (mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
|
||||
if (latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar != 0) {
|
||||
inputView.setSpacebarTextFadeFactor(needsToDisplayLanguage ? 1.0f
|
||||
: mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar, keyboard);
|
||||
: latinIme.mSettingsValues.mFinalFadeoutFactorOfLanguageOnSpacebar,
|
||||
keyboard);
|
||||
}
|
||||
// The fadeout animation will start when the delay is positive.
|
||||
if (localeChanged && mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
|
||||
if (localeChanged
|
||||
&& latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar > 0) {
|
||||
sendMessageDelayed(obtainMessage(MSG_FADEOUT_LANGUAGE_ON_SPACEBAR, keyboard),
|
||||
mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
|
||||
latinIme.mSettingsValues.mDelayBeforeFadeoutLanguageOnSpacebar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +343,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
|
|||
public void startDoubleSpacesTimer() {
|
||||
removeMessages(MSG_SPACE_TYPED);
|
||||
sendMessageDelayed(obtainMessage(MSG_SPACE_TYPED),
|
||||
mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
|
||||
getOuterInstance().mSettingsValues.mDoubleSpacesTurnIntoPeriodTimeout);
|
||||
}
|
||||
|
||||
public void cancelDoubleSpacesTimer() {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class StaticInnerHandlerWrapper<T> extends Handler {
|
||||
final private WeakReference<T> mOuterInstanceRef;
|
||||
|
||||
public StaticInnerHandlerWrapper(T outerInstance) {
|
||||
super();
|
||||
if (outerInstance == null) throw new NullPointerException("outerInstance is null");
|
||||
mOuterInstanceRef = new WeakReference<T>(outerInstance);
|
||||
}
|
||||
|
||||
public StaticInnerHandlerWrapper(T outerInstance, Looper looper) {
|
||||
super(looper);
|
||||
if (outerInstance == null) throw new NullPointerException("outerInstance is null");
|
||||
mOuterInstanceRef = new WeakReference<T>(outerInstance);
|
||||
}
|
||||
|
||||
public T getOuterInstance() {
|
||||
return mOuterInstanceRef.get();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue