View clipping tweaks (#46933)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/46933

Some small tweaks to either resolve or better log clipping-related crashes in ReactViewGroup
Changelog: [Internal]

Reviewed By: sammy-SC

Differential Revision: D63914809

fbshipit-source-id: cf8bfd260c6affb85b8e1ac13447ae9f01d19135
This commit is contained in:
Thomas Nardone
2024-10-10 08:32:15 -07:00
committed by Facebook GitHub Bot
parent ca0abd1b9e
commit 6c35ff92dc
2 changed files with 28 additions and 5 deletions
@@ -411,7 +411,7 @@ public class SurfaceMountingManager {
try {
getViewGroupManager(parentViewState).addView(parentView, view, index);
} catch (IllegalStateException e) {
} catch (IllegalStateException | IndexOutOfBoundsException e) {
// Wrap error with more context for debugging
throw new IllegalStateException(
"addViewAt: failed to insert view ["
@@ -90,7 +90,7 @@ public class ReactViewGroup extends ViewGroup
*/
private static final class ChildrenLayoutChangeListener implements View.OnLayoutChangeListener {
private final ReactViewGroup mParent;
@Nullable private ReactViewGroup mParent;
private ChildrenLayoutChangeListener(ReactViewGroup parent) {
mParent = parent;
@@ -107,12 +107,18 @@ public class ReactViewGroup extends ViewGroup
int oldTop,
int oldRight,
int oldBottom) {
if (mParent.getRemoveClippedSubviews()) {
if (mParent != null && mParent.getRemoveClippedSubviews()) {
mParent.updateSubviewClipStatus(v);
}
}
public void shutdown() {
mParent = null;
}
}
private int mRecycleCount = 0;
// Following properties are here to support the option {@code removeClippedSubviews}. This is a
// temporary optimization/hack that is mainly applicable to the large list of images. The way
// it's implemented is that we store an additional array of children in view node. We selectively
@@ -145,7 +151,7 @@ public class ReactViewGroup extends ViewGroup
/**
* Set all default values here as opposed to in the constructor or field defaults. It is important
* that these properties are set during the constructor, but also on-demand whenever an existing
* ReactTextView is recycled.
* ReactViewGroup is recycled.
*/
private void initView() {
setClipChildren(false);
@@ -168,8 +174,10 @@ public class ReactViewGroup extends ViewGroup
}
/* package */ void recycleView() {
mRecycleCount++;
// Remove dangling listeners
if (mAllChildren != null && mChildrenLayoutChangeListener != null) {
mChildrenLayoutChangeListener.shutdown();
for (int i = 0; i < mAllChildrenCount; i++) {
mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener);
}
@@ -403,7 +411,22 @@ public class ReactViewGroup extends ViewGroup
Assertions.assertNotNull(mAllChildren);
int clippedSoFar = 0;
for (int i = 0; i < mAllChildrenCount; i++) {
updateSubviewClipStatus(clippingRect, i, clippedSoFar);
try {
updateSubviewClipStatus(clippingRect, i, clippedSoFar);
} catch (IndexOutOfBoundsException e) {
throw new IllegalStateException(
"Invalid clipping state. i="
+ i
+ " clippedSoFar="
+ clippedSoFar
+ " count="
+ getChildCount()
+ " allChildrenCount="
+ mAllChildrenCount
+ " recycleCount="
+ mRecycleCount,
e);
}
if (mAllChildren[i].getParent() == null) {
clippedSoFar++;
}