Fix race conditions in DrawView.

Summary:
Currently we have race conditions in DrawView related to isViewGroupClipped, where we create a copy of the DrawView before we update the clipping state, and think the view is unclipped in the next iteration.

Also we are sometimes creating a DrawView with a reactTag of 0.

This fixes both, and is part of the upcoming DrawView bounds change, but is a separate issue that is live in current source.

Reviewed By: ahmedre

Differential Revision: D3598499
This commit is contained in:
Seth Kirby
2016-07-21 18:17:31 -07:00
committed by Ahmed El-Helw
parent 72e665abb4
commit a848ce8efd
3 changed files with 98 additions and 24 deletions

View File

@@ -43,6 +43,9 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper;
private static final String PROP_REMOVE_CLIPPED_SUBVIEWS =
ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS;
private static final Rect LOGICAL_OFFSET_EMPTY = new Rect();
// When we first initialize a backing view, we create a view we are going to throw away anyway,
// so instead initialize with a shared view.
private static final DrawView EMPTY_DRAW_VIEW = new DrawView(0);
private DrawCommand[] mDrawCommands = DrawCommand.EMPTY_ARRAY;
private AttachDetachListener[] mAttachDetachListeners = AttachDetachListener.EMPTY_ARRAY;
@@ -455,7 +458,9 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper;
}
if (mDrawView == null) {
mDrawView = new DrawView(getReactTag(), 0, 0, 0, 0);
// Create a new DrawView, but we might not know our react tag yet, so set it to 0 in the
// meantime.
mDrawView = EMPTY_DRAW_VIEW;
invalidate();
// reset NodeRegion to allow it getting garbage-collected
@@ -464,10 +469,16 @@ import com.facebook.react.views.view.ReactClippingViewGroupHelper;
}
/* package */ final DrawView collectDrawView(float left, float top, float right, float bottom) {
if (!Assertions.assumeNotNull(mDrawView).clipBoundsMatch(left, top, right, bottom)) {
mDrawView = new DrawView(getReactTag(), left, top, right, bottom);
Assertions.assumeNotNull(mDrawView);
if (mDrawView.reactTag == 0) {
// This is the first time we have collected this DrawView, but we have to create a new
// DrawView anyway, as reactTag is final.
mDrawView = new DrawView(getReactTag()).collectDrawView(left, top, right, bottom);
} else {
// We have collected the DrawView before, so the react tag is correct, but we may need a new
// copy with updated bounds. If the bounds match, the same view is returned.
mDrawView = mDrawView.collectDrawView(left, top, right, bottom);
}
return mDrawView;
}