Fix memory leak in edit-text.android

Fix fromObjectRecursive to doesn't override source object
This commit is contained in:
Hristo Hristov
2018-01-11 13:25:03 +02:00
parent 82f081d603
commit 18fe9392d6
5 changed files with 62 additions and 36 deletions

View File

@@ -559,3 +559,10 @@ export function test_get_set_on_observables_fromObject_with_property_in_json() {
TKUnit.assertEqual(value1, array); TKUnit.assertEqual(value1, array);
TKUnit.assertEqual(value2, array); TKUnit.assertEqual(value2, array);
} }
export function test_fromObjectRecursive_does_not_override_source_object_property() {
const myObj = {};
const source = { name: "a", value: myObj };
const observable = fromObjectRecursive(source);
TKUnit.assertEqual(source.value, myObj);
}

View File

@@ -348,11 +348,11 @@ function showReportPage(finalMessage: string) {
page.content = stack; page.content = stack;
messageContainer.focus(); messageContainer.focus();
page.style.fontSize = 11; page.style.fontSize = 11;
if (page.android) { if (platform.isAndroid) {
setTimeout(() => { page.on('navigatedTo', () => {
messageContainer.dismissSoftInput(); messageContainer.focus();
(<android.view.View>messageContainer.nativeViewProtected).scrollTo(0, 0); setTimeout(() => messageContainer.dismissSoftInput());
}, 500); });
} }
return page; return page;

View File

@@ -218,13 +218,17 @@ function addPropertiesFromObject(observable: ObservableFromObject, source: any,
let isRecursive = recursive; let isRecursive = recursive;
for (let prop in source) { for (let prop in source) {
if (source.hasOwnProperty(prop)) { if (source.hasOwnProperty(prop)) {
if (isRecursive) { let value = source[prop];
if (!Array.isArray(source[prop]) && source[prop] && typeof source[prop] === 'object' && !(source[prop] instanceof Observable)) { if (isRecursive
source[prop] = fromObjectRecursive(source[prop]); && !Array.isArray(value)
} && value
&& typeof value === 'object'
&& !(value instanceof Observable)) {
value = fromObjectRecursive(value);
} }
defineNewProperty(observable, prop); defineNewProperty(observable, prop);
observable.set(prop, source[prop]); observable.set(prop, value);
} }
} }
} }

View File

@@ -251,10 +251,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
this._style = new Style(this); this._style = new Style(this);
} }
// Used in Angular.
get parentNode() { get parentNode() {
return this._templateParent || this.parent; return this._templateParent || this.parent;
} }
set parentNode(node: ViewBase) { set parentNode(node: ViewBase) {
this._templateParent = node; this._templateParent = node;
} }

View File

@@ -10,7 +10,8 @@ import { ad } from "../../utils/utils";
export * from "./editable-text-base-common"; export * from "./editable-text-base-common";
//https://github.com/NativeScript/NativeScript/issues/2942 //https://github.com/NativeScript/NativeScript/issues/2942
let dismissKeyboardTimeoutId: any; export let dismissKeyboardTimeoutId: NodeJS.Timer;
export let dismissKeyboardOwner: WeakRef<EditableTextBase>;
interface EditTextListeners extends android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener { interface EditTextListeners extends android.text.TextWatcher, android.view.View.OnFocusChangeListener, android.widget.TextView.OnEditorActionListener {
} }
@@ -22,6 +23,30 @@ interface EditTextListenersClass {
let EditTextListeners: EditTextListenersClass; let EditTextListeners: EditTextListenersClass;
function clearDismissTimer(): void {
dismissKeyboardOwner = null;
if (dismissKeyboardTimeoutId) {
clearTimeout(dismissKeyboardTimeoutId);
dismissKeyboardTimeoutId = null;
}
}
function dismissSoftInput(owner: EditableTextBase): void {
clearDismissTimer();
if (!dismissKeyboardTimeoutId) {
dismissKeyboardTimeoutId = setTimeout(() => {
const owner = dismissKeyboardOwner && dismissKeyboardOwner.get();
const activity = (owner && owner._context) as android.app.Activity;
const nativeView = owner && owner.nativeViewProtected;
dismissKeyboardTimeoutId = null;
dismissKeyboardOwner = null;
const focused = activity && activity.getCurrentFocus();
if (!focused || !(focused instanceof android.widget.EditText)) {
ad.dismissSoftInput(nativeView);
}
}, 10);
}
}
function initializeEditTextListeners(): void { function initializeEditTextListeners(): void {
if (EditTextListeners) { if (EditTextListeners) {
return; return;
@@ -71,7 +96,7 @@ function initializeEditTextListeners(): void {
} }
if (hasFocus) { if (hasFocus) {
owner.clearDismissTimer(); clearDismissTimer();
owner.notify({ eventName: EditableTextBase.focusEvent, object: owner }); owner.notify({ eventName: EditableTextBase.focusEvent, object: owner });
} else { } else {
if (owner._dirtyTextAccumulator || owner._dirtyTextAccumulator === "") { if (owner._dirtyTextAccumulator || owner._dirtyTextAccumulator === "") {
@@ -80,7 +105,7 @@ function initializeEditTextListeners(): void {
} }
owner.notify({ eventName: EditableTextBase.blurEvent, object: owner }); owner.notify({ eventName: EditableTextBase.blurEvent, object: owner });
owner.dismissSoftInput(); dismissSoftInput(owner);
} }
} }
@@ -129,7 +154,6 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
private _inputType: number; private _inputType: number;
public _changeFromCode: boolean; public _changeFromCode: boolean;
public _dismissId: NodeJS.Timer;
public abstract _configureEditText(editText: android.widget.EditText): void; public abstract _configureEditText(editText: android.widget.EditText): void;
@@ -168,35 +192,26 @@ export abstract class EditableTextBase extends EditableTextBaseCommon {
this.nativeViewProtected.setInputType(this._inputType); this.nativeViewProtected.setInputType(this._inputType);
} }
public onUnloaded() {
this.dismissSoftInput();
super.onUnloaded();
}
public dismissSoftInput() { public dismissSoftInput() {
const nativeView = this.nativeViewProtected; const nativeView = this.nativeViewProtected;
if (!nativeView) { if (!nativeView) {
return; return;
} }
const activity = this._context as android.app.Activity; ad.dismissSoftInput(nativeView);
if (!this._dismissId) {
this._dismissId = setTimeout(() => {
this._dismissId = null;
const focused = activity.getCurrentFocus();
if (!focused
|| focused === nativeView
|| !(focused instanceof android.widget.EditText)) {
ad.dismissSoftInput(nativeView);
}
}, 100);
}
}
public clearDismissTimer(): void {
if (this._dismissId) {
clearTimeout(this._dismissId);
this._dismissId = null;
}
} }
public focus(): boolean { public focus(): boolean {
this.clearDismissTimer(); const nativeView = this.nativeViewProtected;
if (!nativeView) {
return;
}
const result = super.focus(); const result = super.focus();
if (result) { if (result) {
ad.showSoftInput(this.nativeViewProtected); ad.showSoftInput(this.nativeViewProtected);