Skip to content

Commit

Permalink
Two ReactART TODOs implemented on Android
Browse files Browse the repository at this point in the history
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.
![screenshot_2016-08-19-16-45-43](https://cloud.githubusercontent.com/assets/18415611/17811741/cafc35c4-662c-11e6-8a63-7c35ef1c5ba9.png)
Closes #9486

Differential Revision: D4021303

Pulled By: foghina
  • Loading branch information
tepamid authored and Ahmed El-Helw committed Dec 19, 2016
1 parent 698774d commit e1b0d32
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@

package com.facebook.react.flat;

import android.graphics.Bitmap;

import com.facebook.csslayout.CSSMeasureMode;
import com.facebook.csslayout.CSSNodeAPI;
import com.facebook.csslayout.MeasureOutput;
Expand Down Expand Up @@ -60,6 +58,6 @@ protected ARTSurfaceView createViewInstance(ThemedReactContext reactContext) {

@Override
public void updateExtraData(ARTSurfaceView root, Object extraData) {
root.setBitmap((Bitmap) extraData);
root.setSurfaceTextureListener((FlatARTSurfaceViewShadowNode) extraData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,26 @@

package com.facebook.react.flat;

import android.graphics.Bitmap;
import javax.annotation.Nullable;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.SurfaceTexture;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;

import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.UIViewOperationQueue;
import com.facebook.react.views.art.ARTVirtualNode;

/* package */ class FlatARTSurfaceViewShadowNode extends FlatShadowNode implements AndroidView {
/* package */ class FlatARTSurfaceViewShadowNode extends FlatShadowNode
implements AndroidView, TextureView.SurfaceTextureListener {
private boolean mPaddingChanged = false;
private @Nullable Surface mSurface;

/* package */ FlatARTSurfaceViewShadowNode() {
forceMountToView();
Expand All @@ -37,24 +48,42 @@ public boolean isVirtualAnchor() {
@Override
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
super.onCollectExtraUpdates(uiUpdater);
uiUpdater.enqueueUpdateExtraData(getReactTag(), drawOutput());
uiUpdater.enqueueUpdateExtraData(getReactTag(), this);
}

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) {
Log.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost");
}
}

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);
private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) {
for (int i = 0; i < shadowNode.getChildCount(); i++) {
ReactShadowNode child = shadowNode.getChildAt(i);
child.markUpdateSeen();
markChildrenUpdatesSeen(child);
}
return bitmap;
}

@Override
Expand All @@ -79,4 +108,23 @@ public void setPadding(int spacingType, float padding) {
dirty();
}
}

@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) {}
}

0 comments on commit e1b0d32

Please sign in to comment.