Ionic 2 Video (<video>) Memory Leak / Garbage Collection Solved


#1

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.


#2

Thanks very much for this post. It helped me solve a problem. One thing I wanted to add: Ionic 2 caches pages, and I found that ngOnDestroy() was not firing when I expected it to. Also, as far as I can tell, the Ionic documentation gives no guarantees about what will be destroyed when. (I might have missed something of course.) However, Ionic does guarantee the ability to detect when a page is no longer the active page. So I put the video release inside ionViewDidLeave() and that seems to work.