refactor(grid-list): avoid recreating tile coordinator for every change detection (#13226)

Currently we recreate the `TileCoordinator` and throw out the old one on every change detection run. These changes reuse a single `TileCoordinator` and update it instead, which ends up shaving off a couple of milliseconds off each layout and reduces the amount of objects that need to be garbage collected.

**Note:** this is a breaking API change for the `TileCoordinator`, however it isn't exported through `material/grid-list`.
This commit is contained in:
Kristiyan Kostadinov
2018-09-25 16:08:28 +02:00
committed by Jeremy Elbourn
parent 0ac41a0896
commit 18f46cfbbd
2 changed files with 23 additions and 6 deletions
+10 -1
View File
@@ -47,6 +47,9 @@ export class MatGridList implements OnInit, AfterContentChecked {
/** Number of columns being rendered. */
private _cols: number;
/** Used for determiningthe position of each tile in the grid. */
private _tileCoordinator: TileCoordinator;
/**
* Row height value passed in by user. This can be one of three types:
* - Number value (ex: "100px"): sets a fixed row height to that value
@@ -135,8 +138,14 @@ export class MatGridList implements OnInit, AfterContentChecked {
/** Computes and applies the size and position for all children grid tiles. */
private _layoutTiles(): void {
const tracker = new TileCoordinator(this.cols, this._tiles);
if (!this._tileCoordinator) {
this._tileCoordinator = new TileCoordinator(this._tiles);
}
const tracker = this._tileCoordinator;
const direction = this._dir ? this._dir.value : 'ltr';
this._tileCoordinator.update(this.cols);
this._tileStyler.init(this.gutterSize, tracker, this.cols, direction);
this._tiles.forEach((tile, index) => {
+13 -5
View File
@@ -44,7 +44,7 @@ export class TileCoordinator {
* Ex: A list with 1 row that contains a tile with rowspan 2 will have a total rowspan of 2.
*/
get rowspan() {
let lastRowMax = Math.max(...this.tracker);
const lastRowMax = Math.max(...this.tracker);
// if any of the tiles has a rowspan that pushes it beyond the total row count,
// add the difference to the rowcount
return lastRowMax > 1 ? this.rowCount + lastRowMax - 1 : this.rowCount;
@@ -53,17 +53,25 @@ export class TileCoordinator {
/** The computed (row, col) position of each tile (the output). */
positions: TilePosition[];
constructor(numColumns: number, tiles: QueryList<MatGridTile>) {
constructor(private _tiles: QueryList<MatGridTile>) {}
/**
* Updates the tile positions.
* @param numColumns Amount of columns in the grid.
*/
update(numColumns: number) {
this.columnIndex = 0;
this.rowIndex = 0;
this.tracker = new Array(numColumns);
this.tracker.fill(0, 0, this.tracker.length);
this.positions = tiles.map(tile => this._trackTile(tile));
this.positions = this._tiles.map(tile => this._trackTile(tile));
}
/** Calculates the row and col position of a tile. */
private _trackTile(tile: MatGridTile): TilePosition {
// Find a gap large enough for this tile.
let gapStartIndex = this._findMatchingGap(tile.colspan);
const gapStartIndex = this._findMatchingGap(tile.colspan);
// Place tile in the resulting gap.
this._markTilePosition(gapStartIndex, tile);