mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 19:26:42 +08:00
fix(android): memory leak with EditableTextBase (#10052)
This commit is contained in:
@ -27,12 +27,11 @@ function clearDismissTimer(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function dismissSoftInput(_owner: WeakRef<EditableTextBase>): void {
|
||||
function dismissSoftInput(view: EditableTextBase): void {
|
||||
clearDismissTimer();
|
||||
if (!dismissKeyboardTimeoutId) {
|
||||
dismissKeyboardTimeoutId = setTimeout(() => {
|
||||
const owner = _owner && _owner.get();
|
||||
const activity = owner?._context as androidx.appcompat.app.AppCompatActivity;
|
||||
const activity = view._context as androidx.appcompat.app.AppCompatActivity;
|
||||
dismissKeyboardTimeoutId = null;
|
||||
const focused = activity && activity.getCurrentFocus();
|
||||
if (focused && !(focused instanceof android.widget.EditText)) {
|
||||
@ -61,81 +60,23 @@ function initializeEditTextListeners(): void {
|
||||
}
|
||||
|
||||
public beforeTextChanged(text: string, start: number, count: number, after: number): void {
|
||||
//
|
||||
this.owner?.get()?.beforeTextChanged(text, start, count, after);
|
||||
}
|
||||
|
||||
public onTextChanged(text: string, start: number, before: number, count: number): void {
|
||||
// const owner = this.owner;
|
||||
// let selectionStart = owner.android.getSelectionStart();
|
||||
// owner.android.removeTextChangedListener(owner._editTextListeners);
|
||||
// owner.android.addTextChangedListener(owner._editTextListeners);
|
||||
// owner.android.setSelection(selectionStart);
|
||||
this.owner?.get()?.onTextChanged(text, start, before, count);
|
||||
}
|
||||
|
||||
public afterTextChanged(editable: android.text.Editable): void {
|
||||
const owner = this.owner && this.owner.get();
|
||||
if (!owner || owner._changeFromCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (owner.updateTextTrigger) {
|
||||
case 'focusLost':
|
||||
owner._dirtyTextAccumulator = editable.toString();
|
||||
break;
|
||||
case 'textChanged':
|
||||
textProperty.nativeValueChange(owner, editable.toString());
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid updateTextTrigger: ' + owner.updateTextTrigger);
|
||||
}
|
||||
this.owner?.get()?.afterTextChanged(editable);
|
||||
}
|
||||
|
||||
public onFocusChange(view: android.view.View, hasFocus: boolean): void {
|
||||
const owner = this.owner && this.owner.get();
|
||||
if (!owner) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasFocus) {
|
||||
clearDismissTimer();
|
||||
owner.notify({
|
||||
eventName: EditableTextBase.focusEvent,
|
||||
object: owner,
|
||||
});
|
||||
} else {
|
||||
if (owner._dirtyTextAccumulator || owner._dirtyTextAccumulator === '') {
|
||||
textProperty.nativeValueChange(owner, owner._dirtyTextAccumulator);
|
||||
owner._dirtyTextAccumulator = undefined;
|
||||
}
|
||||
|
||||
owner.notify({
|
||||
eventName: EditableTextBase.blurEvent,
|
||||
object: owner,
|
||||
});
|
||||
dismissSoftInput(this.owner);
|
||||
}
|
||||
this.owner?.get()?.onFocusChange(view, hasFocus);
|
||||
}
|
||||
|
||||
public onEditorAction(textView: android.widget.TextView, actionId: number, event: android.view.KeyEvent): boolean {
|
||||
const owner = this.owner && this.owner.get();
|
||||
if (!owner) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_DONE || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_UNSPECIFIED || (event && event.getKeyCode() === android.view.KeyEvent.KEYCODE_ENTER)) {
|
||||
// If it is TextField, close the keyboard. If it is TextView, do not close it since the TextView is multiline
|
||||
// https://github.com/NativeScript/NativeScript/issues/3111
|
||||
if (textView.getMaxLines() === 1) {
|
||||
owner.dismissSoftInput();
|
||||
}
|
||||
|
||||
owner._onReturnPress();
|
||||
} else if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_NEXT || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS) {
|
||||
// do not close keyboard for ACTION_NEXT or ACTION_PREVIOUS
|
||||
owner._onReturnPress();
|
||||
}
|
||||
|
||||
return false;
|
||||
return this.owner?.get()?.onEditorAction(textView, actionId, event) || false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +119,12 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
|
||||
}
|
||||
|
||||
public disposeNativeView(): void {
|
||||
(<any>this.nativeTextViewProtected).listener.owner = null;
|
||||
const editText = this.nativeTextViewProtected;
|
||||
editText.removeTextChangedListener((<any>editText).listener);
|
||||
editText.setOnFocusChangeListener(null);
|
||||
editText.setOnEditorActionListener(null);
|
||||
(<any>editText).listener.owner = null;
|
||||
(<any>editText).listener = null;
|
||||
this._keyListenerCache = null;
|
||||
super.disposeNativeView();
|
||||
}
|
||||
@ -531,4 +477,72 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public beforeTextChanged(text: string, start: number, count: number, after: number): void {
|
||||
// called by android.text.TextWatcher
|
||||
}
|
||||
|
||||
public onTextChanged(text: string, start: number, before: number, count: number): void {
|
||||
// called by android.text.TextWatcher
|
||||
// const owner = this.owner;
|
||||
// let selectionStart = owner.android.getSelectionStart();
|
||||
// owner.android.removeTextChangedListener(owner._editTextListeners);
|
||||
// owner.android.addTextChangedListener(owner._editTextListeners);
|
||||
// owner.android.setSelection(selectionStart);
|
||||
}
|
||||
|
||||
public afterTextChanged(editable: android.text.Editable): void {
|
||||
// called by android.text.TextWatcher
|
||||
if (this._changeFromCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (this.updateTextTrigger) {
|
||||
case 'focusLost':
|
||||
this._dirtyTextAccumulator = editable.toString();
|
||||
break;
|
||||
case 'textChanged':
|
||||
textProperty.nativeValueChange(this, editable.toString());
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid updateTextTrigger: ' + this.updateTextTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
public onFocusChange(view: android.view.View, hasFocus: boolean): void {
|
||||
if (hasFocus) {
|
||||
clearDismissTimer();
|
||||
this.notify({
|
||||
eventName: EditableTextBase.focusEvent,
|
||||
object: this,
|
||||
});
|
||||
} else {
|
||||
if (this._dirtyTextAccumulator || this._dirtyTextAccumulator === '') {
|
||||
textProperty.nativeValueChange(this, this._dirtyTextAccumulator);
|
||||
this._dirtyTextAccumulator = undefined;
|
||||
}
|
||||
|
||||
this.notify({
|
||||
eventName: EditableTextBase.blurEvent,
|
||||
});
|
||||
dismissSoftInput(this);
|
||||
}
|
||||
}
|
||||
|
||||
public onEditorAction(textView: android.widget.TextView, actionId: number, event: android.view.KeyEvent): boolean {
|
||||
if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_DONE || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_UNSPECIFIED || (event && event.getKeyCode() === android.view.KeyEvent.KEYCODE_ENTER)) {
|
||||
// If it is TextField, close the keyboard. If it is TextView, do not close it since the TextView is multiline
|
||||
// https://github.com/NativeScript/NativeScript/issues/3111
|
||||
if (textView.getMaxLines() === 1) {
|
||||
this.dismissSoftInput();
|
||||
}
|
||||
|
||||
this._onReturnPress();
|
||||
} else if (actionId === android.view.inputmethod.EditorInfo.IME_ACTION_NEXT || actionId === android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS) {
|
||||
// do not close keyboard for ACTION_NEXT or ACTION_PREVIOUS
|
||||
this._onReturnPress();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user