mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-07 22:40:55 +08:00
Two ReactART TODOs implemented on Android
Summary: Implemented 2 TODOs from ReactART for Android: - TODO(7255985): Use TextureView and pass Surface from the view to draw on it asynchronously instead of passing the bitmap (which is inefficient especially in terms of memory usage) - TODO(6352067): Support dashes in ARTShape We use ReactNativeART in our Android project. 1. Our app crashes sometimes on large screen smartphones with OutOfMemoryError. Crashes happen in ARTSurfaceShadowNode where TODO(7255985) was suggested in a comment in order to use memory more efficiently. 2. We needed dashes for drawing on ARTSurface. **Test plan (required)** I attach a screenshot of our app which shows dashed-lines and two ARTSurfaces on top of each other rendering exactly the same as in the pervious implementation of ARTSurface.  Closes https://github.com/facebook/react-native/pull/9486 Differential Revision: D4021303 Pulled By: foghina fbshipit-source-id: 880175e841e3c598013982a7748b6fc691c7e8d6
This commit is contained in:
committed by
Facebook Github Bot
parent
8acf1a052e
commit
d294e15c43
@@ -15,6 +15,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.DashPathEffect;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
@@ -158,8 +159,7 @@ public class ARTShapeShadowNode extends ARTVirtualNode {
|
||||
(int) (mStrokeColor[1] * 255),
|
||||
(int) (mStrokeColor[2] * 255));
|
||||
if (mStrokeDash != null && mStrokeDash.length > 0) {
|
||||
// TODO(6352067): Support dashes
|
||||
FLog.w(ReactConstants.TAG, "ART: Dashes are not supported yet!");
|
||||
paint.setPathEffect(new DashPathEffect(mStrokeDash, 0));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,37 +9,15 @@
|
||||
|
||||
package com.facebook.react.views.art;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.view.View;
|
||||
import android.view.TextureView;
|
||||
|
||||
/**
|
||||
* Custom {@link View} implementation that draws an ARTSurface React view and its children.
|
||||
*/
|
||||
public class ARTSurfaceView extends View {
|
||||
|
||||
private @Nullable Bitmap mBitmap;
|
||||
|
||||
public class ARTSurfaceView extends TextureView {
|
||||
public ARTSurfaceView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void setBitmap(Bitmap bitmap) {
|
||||
if (mBitmap != null) {
|
||||
mBitmap.recycle();
|
||||
}
|
||||
mBitmap = bitmap;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
if (mBitmap != null) {
|
||||
canvas.drawBitmap(mBitmap, 0, 0, null);
|
||||
}
|
||||
setOpaque(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
|
||||
package com.facebook.react.views.art;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.facebook.csslayout.CSSMeasureMode;
|
||||
import com.facebook.csslayout.CSSNodeAPI;
|
||||
import com.facebook.csslayout.MeasureOutput;
|
||||
@@ -63,6 +61,6 @@ public class ARTSurfaceViewManager extends
|
||||
|
||||
@Override
|
||||
public void updateExtraData(ARTSurfaceView root, Object extraData) {
|
||||
root.setBitmap((Bitmap) extraData);
|
||||
root.setSurfaceTextureListener((ARTSurfaceViewShadowNode) extraData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,17 +9,29 @@
|
||||
|
||||
package com.facebook.react.views.art;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Color;
|
||||
import android.view.Surface;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.view.TextureView;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
|
||||
/**
|
||||
* Shadow node for ART virtual tree root - ARTSurfaceView
|
||||
*/
|
||||
public class ARTSurfaceViewShadowNode extends LayoutShadowNode {
|
||||
public class ARTSurfaceViewShadowNode extends LayoutShadowNode
|
||||
implements TextureView.SurfaceTextureListener {
|
||||
|
||||
private @Nullable Surface mSurface;
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
@@ -34,23 +46,61 @@ public class ARTSurfaceViewShadowNode extends LayoutShadowNode {
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
|
||||
super.onCollectExtraUpdates(uiUpdater);
|
||||
uiUpdater.enqueueUpdateExtraData(getReactTag(), drawOutput());
|
||||
drawOutput();
|
||||
uiUpdater.enqueueUpdateExtraData(getReactTag(), this);
|
||||
}
|
||||
|
||||
private Object drawOutput() {
|
||||
// TODO(7255985): Use TextureView and pass Surface from the view to draw on it asynchronously
|
||||
// instead of passing the bitmap (which is inefficient especially in terms of memory usage)
|
||||
Bitmap bitmap = Bitmap.createBitmap(
|
||||
(int) getLayoutWidth(),
|
||||
(int) getLayoutHeight(),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ARTVirtualNode child = (ARTVirtualNode) getChildAt(i);
|
||||
child.draw(canvas, paint, 1f);
|
||||
child.markUpdateSeen();
|
||||
private void drawOutput() {
|
||||
if (mSurface == null || !mSurface.isValid()) {
|
||||
markChildrenUpdatesSeen(this);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Canvas canvas = mSurface.lockCanvas(null);
|
||||
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
|
||||
Paint paint = new Paint();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
ARTVirtualNode child = (ARTVirtualNode) getChildAt(i);
|
||||
child.draw(canvas, paint, 1f);
|
||||
child.markUpdateSeen();
|
||||
}
|
||||
|
||||
if (mSurface == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSurface.unlockCanvasAndPost(canvas);
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost");
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) {
|
||||
for (int i = 0; i < shadowNode.getChildCount(); i++) {
|
||||
ReactShadowNode child = shadowNode.getChildAt(i);
|
||||
child.markUpdateSeen();
|
||||
markChildrenUpdatesSeen(child);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||
mSurface = new Surface(surface);
|
||||
drawOutput();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
||||
surface.release();
|
||||
mSurface = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user