My app is a side-menu style where each @Page
contains text and multiple <video>
elements. Each time the play button on a video is pressed in iOS, there would be a jump of memory, as shown below.
The problem
Then when I would go to a new page of the app (with more videos), the memory associated with the videos on the previous page was not garbage collected. After reading a few sections and playing a dozen or so videos, the memory was over 1 Gb.
The solution
As decribed in the W3 HTML5 video spec best practices, it is important to release resources held by media elements when they are no longer needed. The spec recommends setting the src
attribute to ''
and then calling the load()
method.
My implementation of this solution in Angular 2 was to wrap the <video>
elements in a @Component
and use the ngOnDestroy()
lifecycle event of the component to set the src
attribute to ''
and then cal the load()
method. Here is an example of a ReleasableVideo
component:
import {Component, Input, ViewChild} from 'angular2/core';
@Component({
selector: "releasable-video",
template: '<video [src]="src" #player></video>'
})
export class ReleasableVideoComponent {
@Input() src : string
@ViewChild('player') player;
constructor() {
}
ngOnDestroy() {
// the .nativeElement property of the ViewChild is the reference to the <video>
this.player.nativeElement.src = '';
this.player.nativeElement.load();
}
The key to making this work is to use @ViewChild
with a template reference variable (#player) to access the video
element within the component and set its src attribute and call load().
After this fix, going to a new @Page
triggers the ngOnDestroy() event for all <releasable-video>
components within the previous @Page
, releasing their resources so the videos can be properly garbage collected, as shown below
I hope this helps some of you. For what it is worth, I had been battling a similar problem in my Ionic 1.x application.