Description
Environment
Provide version numbers for the following components (information can be retrieved by running tns info
in your project folder or by inspecting the package.json
of the project):
- CLI: 5.2.0
- Cross-platform modules:
- Android Runtime: 5.2.0
- iOS Runtime:5.2.0
- Plugin(s):
- NativeScript-Angular: ~7.2.1
- Angular: ~7.2.0
Describe the bug
While working on #1728 I think I’ve found a couple of memory leaks in nativescript-angular.
ListViewComponent/TemplatedItemsComponent items.
In onItemLoading(args) https://github.com/NativeScript/nativescript-angular/blob/master/nativescript-angular/directives/templated-items-comp.ts#L141-L181
The viewRef
is bound to the args.view[NG_VIEW]
.
This is never cleared, so when the ListViewComponent
is destroyed this reference still exists.
I suggest making this a WeakRef
.
The factory functions in TemplatedItemsComponent._templateMap creates a circular reference and should be cleared in ngOnDestroy()
NativeScript views lives on after the angular app have been destroyed.
The native views are destroyed as expected but according to the Chrome debugger the NativeScript views lives on.
This is caused by the AppHostView not being cleared up on exit and the firstChild
, lastChild
and nextSibling
references are not cleaned up.
The AppHostView is reused on next launch, so it shouldn’t itself be deleted but the children should.
Sidenote: AppHostView._ngAppRoot is a reference to the last Frame even after exit, this should be solved by deleting all its children on exit.
ViewUtils.removeChild(parent, child) doesn’t remove children recursively.
ViewUtils sets up the firstChild
, lastChild
and nextSibling
references when a view is added, but doesn’t clear them up properly when a parent view is removes.
I suggest making removeFromQueue(parent, child) and removeFromVisualTree(parent, child) recursive to clear up the references.
PageRouterOutlet doesn’t clear up it’s children.
this.activated
should be destroyed in ngOnDestroy()
NSLocationStrategy don’t have an ngOnDestroy()
This leaves correntOutlet
with a reference to the destroyed PageRouterOutlet
.
To Reproduce
- Create a new nativescript angular app with:
tns create --ng NAME
- Launch the app on android in debug mode and start the Chrome debugger.
- Close the app by tappen the back button, reopen and close the app a few times.
- Go to the memory tab in the Chrome debugger and take a heap snapshot.
- The snapshot will have N (= number of times the app has been opened)
Frame'/
ActionBar/
Page/
PageRouterOutlet, N*8
StackLayout` etc. The native views will have been destroyed.- If you inspect the Views a little closer you should see they hold references to each other via
firstChild
,lastChild
andnextSibling
- If you inspect the Views a little closer you should see they hold references to each other via
Note: It doesn't seem to matter how many times I call GC()
or how long I wait.
Expected behavior
- I expect the
GC()
to have collected the NativeScript Views.
Sample project
https://github.com/m-abs/tns-ng-app-lifecycle
Additional context