diff --git a/tests/app/ui/list-view/list-view-tests.ts b/tests/app/ui/list-view/list-view-tests.ts index b8305cc36..a01b86fe5 100644 --- a/tests/app/ui/list-view/list-view-tests.ts +++ b/tests/app/ui/list-view/list-view-tests.ts @@ -558,6 +558,38 @@ export class ListViewTest extends testModule.UITest { } } + public test_RemovingChildViewsBeforeListView() { + var listView = this.testView; + var converterCalledCounter = 0; + + var testConverter = function (value) { + converterCalledCounter++; + return value; + } + + app.resources["testConverter"] = testConverter; + + var listViewModel = new observable.Observable(); + listViewModel.set("items", [1, 2, 3]); + listView.bindingContext = listViewModel; + + listView.bind({ sourceProperty: "items", targetProperty: "items" }); + listView.itemTemplate = ""; + + this.waitUntilListViewReady(); + + if (platform.isAndroid) { + // simulates Angular way of removing views + (listView)._realizedItems.forEach((view, nativeView, map) => { + console.log("view: " + view); + listView._removeView(view); + }); + this.tearDown(); + // should not crash + TKUnit.assertTrue(true); + } + } + public test_no_memory_leak_when_items_is_regular_array() { let weakRef = new WeakRef(this.testView); weakRef.get().items = FEW_ITEMS; diff --git a/tns-core-modules/ui/list-view/list-view.android.ts b/tns-core-modules/ui/list-view/list-view.android.ts index 1fba3d273..988fabb45 100644 --- a/tns-core-modules/ui/list-view/list-view.android.ts +++ b/tns-core-modules/ui/list-view/list-view.android.ts @@ -108,7 +108,10 @@ export class ListView extends common.ListView { callback(view); } else { - callback(view.parent); + // in some cases (like item is unloaded from another place (like angular) view.parent becomes undefined) + if (view.parent) { + callback(view.parent); + } } }); } @@ -124,12 +127,13 @@ export class ListView extends common.ListView { private clearRealizedCells(): void { // clear the cache this._realizedItems.forEach((view, nativeView, map) => { - // This is to clear the StackLayout that is used to wrap non LayoutBase & ProxyViewContainer instances. - if (!(view.parent instanceof ListView)) { - this._removeView(view.parent); + if (view.parent) { + // This is to clear the StackLayout that is used to wrap non LayoutBase & ProxyViewContainer instances. + if (!(view.parent instanceof ListView)) { + this._removeView(view.parent); + } + view.parent._removeView(view); } - - view.parent._removeView(view); }); this._realizedItems.clear();