feat: requestLayout performance improvements (#9122)

It was unnecessary to make multiple calls requestLayout inside initNativeView (properties set)
This commit is contained in:
farfromrefuge
2021-08-11 20:50:41 +02:00
committed by GitHub
parent 71b856c781
commit e4ce17e156
4 changed files with 47 additions and 2 deletions

View File

@ -1363,6 +1363,8 @@ function inheritableCssPropertyValuesOn(style: Style): Array<{ property: Inherit
type PropertyInterface = Property<ViewBase, any> | CssProperty<Style, any> | CssAnimationProperty<Style, any>; type PropertyInterface = Property<ViewBase, any> | CssProperty<Style, any> | CssAnimationProperty<Style, any>;
export const initNativeView = profile('"properties".initNativeView', function initNativeView(view: ViewBase): void { export const initNativeView = profile('"properties".initNativeView', function initNativeView(view: ViewBase): void {
const wasSuspended = view.suspendRequestLayout;
view.suspendRequestLayout = true;
if (view._suspendedUpdates) { if (view._suspendedUpdates) {
applyPendingNativeSetters(view); applyPendingNativeSetters(view);
} else { } else {
@ -1370,6 +1372,14 @@ export const initNativeView = profile('"properties".initNativeView', function in
} }
// Would it be faster to delete all members of the old object? // Would it be faster to delete all members of the old object?
view._suspendedUpdates = {}; view._suspendedUpdates = {};
// if the view requestLayout was not suspended before
// it means we can request a layout if needed.
// will be done after otherwise
view.suspendRequestLayout = wasSuspended;
if (!wasSuspended && view.isLayoutRequestNeeded) {
view.requestLayout();
}
}); });
export function applyPendingNativeSetters(view: ViewBase): void { export function applyPendingNativeSetters(view: ViewBase): void {

View File

@ -431,7 +431,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
if (this._isLoaded) { if (this._isLoaded) {
return; return;
} }
// the view is going to be layed out after
// no need for requestLayout which can be pretty slow because
// called a lot and going all up the chain to the page
this.suspendRequestLayout = true;
this._isLoaded = true; this._isLoaded = true;
this._cssState.onLoaded(); this._cssState.onLoaded();
this._resumeNativeUpdates(SuspendType.Loaded); this._resumeNativeUpdates(SuspendType.Loaded);
@ -442,6 +445,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
return true; return true;
}); });
this.suspendRequestLayout = false;
this._emit('loaded'); this._emit('loaded');
} }
@ -658,6 +662,20 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
} }
} }
_requestLayoutNeeded = false;
get isLayoutRequestNeeded() {
return this._requestLayoutNeeded;
}
_suspendRequestLayout = false;
set suspendRequestLayout(value: boolean) {
this._suspendRequestLayout = value;
}
get suspendRequestLayout() {
return this._suspendRequestLayout;
}
@profile @profile
public requestLayout(): void { public requestLayout(): void {
// Default implementation for non View instances (like TabViewItem). // Default implementation for non View instances (like TabViewItem).

View File

@ -530,6 +530,11 @@ export class View extends ViewCommon {
@profile @profile
public requestLayout(): void { public requestLayout(): void {
if (this._suspendRequestLayout) {
this._requestLayoutNeeded = true;
return;
}
this._requestLayoutNeeded = false;
super.requestLayout(); super.requestLayout();
if (this.nativeViewProtected) { if (this.nativeViewProtected) {
this.nativeViewProtected.requestLayout(); this.nativeViewProtected.requestLayout();

View File

@ -63,9 +63,21 @@ export class View extends ViewCommon implements ViewDefinition {
this.once(View.loadedEvent, () => setupAccessibleView(this)); this.once(View.loadedEvent, () => setupAccessibleView(this));
} }
requestLayoutIfNeeded() {
if (this.isLayoutRequired) {
this._requestLayoutNeeded = false;
this.requestLayout();
}
}
public requestLayout(): void { public requestLayout(): void {
super.requestLayout(); if (this._suspendRequestLayout) {
this._requestLayoutNeeded = true;
return;
}
this._requestLayoutNeeded = false;
this._privateFlags |= PFLAG_FORCE_LAYOUT; this._privateFlags |= PFLAG_FORCE_LAYOUT;
super.requestLayout();
const nativeView = this.nativeViewProtected; const nativeView = this.nativeViewProtected;
if (nativeView && nativeView.setNeedsLayout) { if (nativeView && nativeView.setNeedsLayout) {