mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-05-01 22:35:29 +08:00
Lazily create/update views
Summary: There is a rare case in React Native when a hierarchy is created and then *immediately* discarded all in one transaction. This is causing a View leak, because a View is created and then never attached to a hierarchy because it shadow node got detached. Since we never attached the View to the hierarchy, we cannot do a detach either and the View is kept in NativeViewHierarchyManager forever, causing a View leak. To fix the issue, don't create a backing View whenever a shadow node mounts to a View. Instead, put the create request into a queue and ONLY execute it if a shadow node is still attached to a hierarchy. This is fixing the View leak because will not create a View unless it's going to be attached somewhere. The same logic applies to View style update (we don't want to update a View that is going to be detached from a hierarchy). Reviewed By: ahmedre Differential Revision: D2916826
This commit is contained in:
committed by
Ahmed El-Helw
parent
bb04967986
commit
ada5234b0e
@@ -43,6 +43,8 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
private final ArrayList<FlatShadowNode> mViewsToDetachAllChildrenFrom = new ArrayList<>();
|
||||
private final ArrayList<FlatShadowNode> mViewsToDetach = new ArrayList<>();
|
||||
private final ArrayList<FlatShadowNode> mViewsToDrop = new ArrayList<>();
|
||||
private final ArrayList<FlatShadowNode> mViewsToUpdate = new ArrayList<>();
|
||||
private final ArrayList<ReactStylesDiffMap> mStylesToUpdate = new ArrayList<>();
|
||||
private final ArrayList<OnLayoutEvent> mOnLayoutEvents = new ArrayList<>();
|
||||
private final ArrayList<FlatUIViewOperationQueue.UpdateViewBounds> mUpdateViewBoundsOperations =
|
||||
new ArrayList<>();
|
||||
@@ -62,6 +64,8 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
* DrawCommands that will then mount in UI thread to a root FlatViewGroup so that it can draw.
|
||||
*/
|
||||
/* package */ void applyUpdates(EventDispatcher eventDispatcher, FlatShadowNode node) {
|
||||
commitViewUpdates();
|
||||
|
||||
float width = node.getLayoutWidth();
|
||||
float height = node.getLayoutHeight();
|
||||
float left = node.getLayoutX();
|
||||
@@ -124,18 +128,8 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
/* package */ void enqueueCreateOrUpdateView(
|
||||
FlatShadowNode node,
|
||||
@Nullable ReactStylesDiffMap styles) {
|
||||
if (node.isBackingViewCreated()) {
|
||||
if (styles != null) {
|
||||
// if the View is already created, make sure propagate new styles.
|
||||
mOperationsQueue.enqueueUpdateProperties(node.getReactTag(), node.getViewClass(), styles);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int tag = node.getReactTag();
|
||||
mOperationsQueue.enqueueCreateView(node.getThemedContext(), tag, node.getViewClass(), styles);
|
||||
|
||||
node.signalBackingViewIsCreated();
|
||||
mViewsToUpdate.add(node);
|
||||
mStylesToUpdate.add(styles);
|
||||
}
|
||||
|
||||
/* package */ void ensureBackingViewIsCreated(FlatShadowNode node) {
|
||||
@@ -153,6 +147,36 @@ import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
mViewsToDrop.add(node);
|
||||
}
|
||||
|
||||
private void commitViewUpdates() {
|
||||
for (int i = 0, numViewsToUpdate = mViewsToUpdate.size(); i != numViewsToUpdate; ++i) {
|
||||
FlatShadowNode node = mViewsToUpdate.get(i);
|
||||
if (node.getParent() == null) {
|
||||
// Shadow node is not attached to the hierarchy, which means it is being discarded.
|
||||
// No need to create or update view in this case, as the View is already gone as well.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.isBackingViewCreated()) {
|
||||
// if the View is already created, make sure propagate new styles.
|
||||
mOperationsQueue.enqueueUpdateProperties(
|
||||
node.getReactTag(),
|
||||
node.getViewClass(),
|
||||
mStylesToUpdate.get(i));
|
||||
} else {
|
||||
mOperationsQueue.enqueueCreateView(
|
||||
node.getThemedContext(),
|
||||
node.getReactTag(),
|
||||
node.getViewClass(),
|
||||
mStylesToUpdate.get(i));
|
||||
|
||||
node.signalBackingViewIsCreated();
|
||||
}
|
||||
}
|
||||
|
||||
mViewsToUpdate.clear();
|
||||
mStylesToUpdate.clear();
|
||||
}
|
||||
|
||||
private void addNodeRegion(
|
||||
FlatShadowNode node,
|
||||
float left,
|
||||
|
||||
Reference in New Issue
Block a user