Skip to content

Commit

Permalink
perf: Reduce interop invocations during MeasureChildOverride
Browse files Browse the repository at this point in the history
  • Loading branch information
jeromelaban committed Feb 4, 2022
1 parent 81e9ce8 commit 19625de
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 18 deletions.
33 changes: 33 additions & 0 deletions src/Uno.UI.BindingHelper.Android/Uno/UI/UnoViewGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,39 @@ public static long getMeasuredDimensions(View view) {
return view.getMeasuredWidth() | (((long)view.getMeasuredHeight()) << 32);
}


/**
* Fast invocation for the request layout logic.
*
* Implemented in java to avoid the interop cost of android-only APIs from managed code.
*/
public static void tryFastRequestLayout(View view, boolean needsForceLayout) {

if (needsForceLayout) {
// Bypass Android cache, to ensure the Child's Measure() is actually invoked.
view.forceLayout();

// This could occur when one of the dimension is _Infinite_: Android will cache the
// value, which is not something we want. Specially when the container is a <StackPanel>.

// Issue: https://github.com/unoplatform/uno/issues/2879
}

if (view.isLayoutRequested())
{
ViewParent parent = view.getParent();

if(parent != null && !parent.isLayoutRequested())
{
// If a view has requested layout but its Parent hasn't, then the tree is in a broken state, because RequestLayout() calls
// cannot bubble up from below the view, and remeasures cannot bubble down from above the parent. This can arise, eg, when
// ForceLayout() is used. To fix this state, call RequestLayout() on the parent. Since MeasureChildOverride() is called
// from the top down, we should be able to assume that the tree above the parent is already in a good state.
parent.requestLayout();
}
}
}

protected final void addViewFast(View view)
{
try
Expand Down
20 changes: 2 additions & 18 deletions src/Uno.UI/UI/Xaml/Controls/Layouter/Layouter.Android.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,9 @@ protected Size MeasureChildOverride(View view, Size slotSize)
var widthSpec = ViewHelper.SpecFromLogicalSize(slotSize.Width);
var heightSpec = ViewHelper.SpecFromLogicalSize(slotSize.Height);

if (double.IsPositiveInfinity(slotSize.Width) || double.IsPositiveInfinity(slotSize.Height))
{
// Bypass Android cache, to ensure the Child's Measure() is actually invoked.
view.ForceLayout();

// This could occur when one of the dimension is _Infinite_: Android will cache the
// value, which is not something we want. Specially when the container is a <StackPanel>.

// Issue: https://github.com/unoplatform/uno/issues/2879
}
var needsForceLayout = double.IsPositiveInfinity(slotSize.Width) || double.IsPositiveInfinity(slotSize.Height);

if (view.IsLayoutRequested && view.Parent is View parent && !parent.IsLayoutRequested)
{
// If a view has requested layout but its Parent hasn't, then the tree is in a broken state, because RequestLayout() calls
// cannot bubble up from below the view, and remeasures cannot bubble down from above the parent. This can arise, eg, when
// ForceLayout() is used. To fix this state, call RequestLayout() on the parent. Since MeasureChildOverride() is called
// from the top down, we should be able to assume that the tree above the parent is already in a good state.
parent.RequestLayout();
}
Uno.UI.Controls.BindableView.TryFastRequestLayout(view, needsForceLayout);

MeasureChild(view, widthSpec, heightSpec);

Expand Down

0 comments on commit 19625de

Please sign in to comment.