Description
What is the expected behavior?
Multiple subscriptions to same media query string should normally unsubscibe.
What is the current behavior?
Multiple subscriptions to same media query string causes memory leak, because only last of them can be GC. Component which wasn't last to subscribe isn't properly gcied and as result, whole component tree is kept in memory with all its data and detached nodes. In my application, this was causing massive memory leaks.
https://github.com/angular/material2/blob/e136fc8707ec3278ba32659e4d77ff21eed6de73/src/cdk/layout/breakpoints-observer.ts#L114
In this code, we are saving listener to closure scoped variable queryListener
, which is rewritten upon next subscripion as we are trying reuse observables with _queries
Map.
Solutions is not to use scoped variable but rather return queryListener
inside addHandler function of fromEventPattern
. Then we can this passed reference use inside removeHandler as second parametr and used it to call mql.removeListener
.
(listener: Function) => {
const queryListener = (e: any) => this.zone.run(() => listener(e));
mql.addListener(queryListener);
return queryListener;
},
(listener, queryListener) => mql.removeListener(queryListener))