Binding for js events
Reviewed By: fkgozali Differential Revision: D8181616 fbshipit-source-id: 5937c83f22ac09e3041fcb0f8d4e9e3026b2b397
This commit is contained in:
parent
23fbd312aa
commit
0f10e03dd8
|
@ -261,7 +261,7 @@ public class ReactAppTestActivity extends FragmentActivity
|
|||
List<ViewManager> viewManagers =
|
||||
mReactInstanceManager.getOrCreateViewManagers(reactApplicationContext);
|
||||
FabricUIManager fabricUIManager =
|
||||
new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers));
|
||||
new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers), jsContext);
|
||||
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
|
||||
return fabricUIManager;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,24 @@
|
|||
package com.facebook.react.fabric;
|
||||
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.NativeMap;
|
||||
|
||||
public interface FabricBinding {
|
||||
|
||||
void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule);
|
||||
|
||||
long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
||||
|
||||
void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
||||
|
||||
void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
||||
|
||||
void dispatchEventToTarget(
|
||||
long jsContextNativePointer,
|
||||
long eventHandlerPointer,
|
||||
long eventTargetPointer,
|
||||
String type,
|
||||
NativeMap payload
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -14,15 +14,15 @@ import static android.view.View.MeasureSpec.UNSPECIFIED;
|
|||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.bridge.GuardedRunnable;
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableNativeMap;
|
||||
import com.facebook.react.bridge.UIManager;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.modules.i18nmanager.I18nUtil;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
|
@ -39,10 +39,8 @@ import com.facebook.react.uimanager.common.MeasureSpecProvider;
|
|||
import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
|
@ -60,14 +58,16 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||
private final ViewManagerRegistry mViewManagerRegistry;
|
||||
private final UIViewOperationQueue mUIViewOperationQueue;
|
||||
private final NativeViewHierarchyManager mNativeViewHierarchyManager;
|
||||
private final JavaScriptContextHolder mJSContext;
|
||||
private volatile int mCurrentBatch = 0;
|
||||
private final FabricReconciler mFabricReconciler;
|
||||
// TODO: Initialize new Binding (waiting for C++ implemenation to be landed)
|
||||
private FabricBinding mBinding;
|
||||
private JavaScriptContextHolder mContext;
|
||||
private long mEventHandlerPointer;
|
||||
|
||||
public FabricUIManager(
|
||||
ReactApplicationContext reactContext, ViewManagerRegistry viewManagerRegistry) {
|
||||
ReactApplicationContext reactContext,
|
||||
ViewManagerRegistry viewManagerRegistry,
|
||||
JavaScriptContextHolder jsContext) {
|
||||
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
|
||||
mReactApplicationContext = reactContext;
|
||||
mViewManagerRegistry = viewManagerRegistry;
|
||||
|
@ -76,10 +76,11 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||
new UIViewOperationQueue(
|
||||
reactContext, mNativeViewHierarchyManager, 0);
|
||||
mFabricReconciler = new FabricReconciler(mUIViewOperationQueue);
|
||||
mJSContext = jsContext;
|
||||
}
|
||||
|
||||
public void registerEventHandler(long eventHandlerPointer) {
|
||||
// TODO: Release this event handler at some point.
|
||||
public void setBinding(FabricBinding binding) {
|
||||
mBinding = binding;
|
||||
}
|
||||
|
||||
/** Creates a new {@link ReactShadowNode} */
|
||||
|
@ -480,20 +481,39 @@ public class FabricUIManager implements UIManager, JSHandler {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(int instanceHandle, String name, WritableMap params) {
|
||||
Log.e(TAG, "Invoking '" + name + "' on instanceHandle: '" + instanceHandle + "' from FabricUIManager.");
|
||||
// -> call to C++
|
||||
}
|
||||
|
||||
public long createEventTarget(int reactTag) throws IllegalStateException {
|
||||
@Nullable
|
||||
public long createEventTarget(int reactTag) {
|
||||
long instanceHandle = mNativeViewHierarchyManager.getInstanceHandle(reactTag);
|
||||
if (instanceHandle == 0) {
|
||||
throw new IllegalStateException("View with reactTag " + reactTag + " does not exist.");
|
||||
long context = mJSContext.get();
|
||||
long eventTarget = mBinding.createEventTarget(context, instanceHandle);
|
||||
if (DEBUG) {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Created EventTarget: " + eventTarget + " for tag: " + reactTag + " with instanceHandle: " + instanceHandle);
|
||||
}
|
||||
|
||||
// TODO: uncomment after diff including Binding is landed
|
||||
// return mBinding.createEventTarget(mContext.get(), instanceHandle);
|
||||
return 0;
|
||||
return eventTarget;
|
||||
}
|
||||
|
||||
public void registerEventHandler(long eventHandlerPointer) {
|
||||
mEventHandlerPointer = eventHandlerPointer;
|
||||
}
|
||||
|
||||
public void releaseEventTarget(long eventTargetPointer) {
|
||||
mBinding.releaseEventTarget(mJSContext.get(), eventTargetPointer);
|
||||
}
|
||||
|
||||
public void releaseEventHandler(long eventHandlerPointer) {
|
||||
mBinding.releaseEventHandler(mJSContext.get(), eventHandlerPointer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(long eventTarget, String name, WritableMap params) {
|
||||
if (DEBUG) {
|
||||
Log.e(
|
||||
TAG,
|
||||
"Dispatching event for target: " + eventTarget);
|
||||
}
|
||||
mBinding.dispatchEventToTarget(mJSContext.get(), mEventHandlerPointer, eventTarget, name, (WritableNativeMap) params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@ import com.facebook.react.bridge.WritableMap;
|
|||
|
||||
public interface JSHandler {
|
||||
|
||||
void invoke(int instanceHandle, String name, WritableMap params);
|
||||
void invoke(long instanceHandle, String name, WritableMap params);
|
||||
|
||||
}
|
||||
|
|
|
@ -49,9 +49,8 @@ public class FabricEventEmitter implements RCTEventEmitter, Closeable {
|
|||
|
||||
@Override
|
||||
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap params) {
|
||||
//TODO get instanceHandle associated with targetTag.
|
||||
int instanceHandle = targetTag;
|
||||
mScheduler.scheduleWork(new FabricUIManagerWork(instanceHandle, eventName, params) );
|
||||
long eventTarget = mFabricUIManager.createEventTarget(targetTag);
|
||||
mScheduler.scheduleWork(new FabricUIManagerWork(eventTarget, eventName, params));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,19 +59,26 @@ public class FabricEventEmitter implements RCTEventEmitter, Closeable {
|
|||
}
|
||||
|
||||
private class FabricUIManagerWork implements Work {
|
||||
private final int mInstanceHandle;
|
||||
private final long mEventTarget;
|
||||
private final String mEventName;
|
||||
private final WritableMap mParams;
|
||||
|
||||
public FabricUIManagerWork(int instanceHandle, String eventName, @Nullable WritableMap params) {
|
||||
mInstanceHandle = instanceHandle;
|
||||
public FabricUIManagerWork(long eventTarget, String eventName, @Nullable WritableMap params) {
|
||||
mEventTarget = eventTarget;
|
||||
mEventName = eventName;
|
||||
mParams = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mFabricUIManager.invoke(mInstanceHandle, mEventName, mParams);
|
||||
try {
|
||||
mFabricUIManager.invoke(mEventTarget, mEventName, mParams);
|
||||
} catch (Throwable t) {
|
||||
Log.e(TAG, "Error sending event " + mEventName, t);
|
||||
//TODO: manage exception properly
|
||||
} finally{
|
||||
mFabricUIManager.releaseEventTarget(mEventTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,17 @@ public class FabricJSCBinding implements FabricBinding {
|
|||
|
||||
private static native HybridData initHybrid();
|
||||
|
||||
private native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
||||
@Override
|
||||
public native long createEventTarget(long jsContextNativePointer, long instanceHandlePointer);
|
||||
|
||||
private native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
||||
@Override
|
||||
public native void releaseEventTarget(long jsContextNativePointer, long eventTargetPointer);
|
||||
|
||||
private native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
||||
@Override
|
||||
public native void releaseEventHandler(long jsContextNativePointer, long eventHandlerPointer);
|
||||
|
||||
private native void dispatchEventToTarget(
|
||||
@Override
|
||||
public native void dispatchEventToTarget(
|
||||
long jsContextNativePointer,
|
||||
long eventHandlerPointer,
|
||||
long eventTargetPointer,
|
||||
|
@ -50,6 +54,7 @@ public class FabricJSCBinding implements FabricBinding {
|
|||
|
||||
@Override
|
||||
public void installFabric(JavaScriptContextHolder jsContext, FabricUIManager fabricModule) {
|
||||
fabricModule.setBinding(this);
|
||||
installFabric(jsContext.get(), fabricModule);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,17 +222,15 @@ public class NativeViewHierarchyManager {
|
|||
@Nullable
|
||||
@TargetApi(Build.VERSION_CODES.DONUT)
|
||||
public long getInstanceHandle(int reactTag) {
|
||||
UiThreadUtil.assertOnUiThread();
|
||||
|
||||
View view = mTagsToViews.get(reactTag);
|
||||
if (view == null) {
|
||||
throw new IllegalArgumentException("Unable to find view for tag: " + reactTag);
|
||||
}
|
||||
Long tag = (Long) view.getTag(R.id.view_tag_instance_handle);
|
||||
if (tag == null) {
|
||||
Long instanceHandle = (Long) view.getTag(R.id.view_tag_instance_handle);
|
||||
if (instanceHandle == null) {
|
||||
throw new IllegalArgumentException("Unable to find instanceHandle for tag: " + reactTag);
|
||||
}
|
||||
return tag;
|
||||
return instanceHandle;
|
||||
}
|
||||
|
||||
private void updateLayout(View viewToUpdate, int x, int y, int width, int height) {
|
||||
|
|
|
@ -115,7 +115,7 @@ public class EventDispatcher implements LifecycleEventListener,
|
|||
for (EventDispatcherListener listener : mListeners) {
|
||||
listener.onEventDispatch(event);
|
||||
}
|
||||
|
||||
|
||||
synchronized (mEventsStagingLock) {
|
||||
mEventStaging.add(event);
|
||||
Systrace.startAsyncFlow(
|
||||
|
|
|
@ -5,6 +5,7 @@ import static org.fest.assertions.api.Assertions.assertThat;
|
|||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.facebook.react.bridge.CatalystInstance;
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.uimanager.NativeViewHierarchyManager;
|
||||
|
@ -41,7 +42,8 @@ public class FabricReconcilerTest {
|
|||
reactContext.initializeWithInstance(catalystInstance);
|
||||
List<ViewManager> viewManagers = new ArrayList<>();
|
||||
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry);
|
||||
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
|
||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext);
|
||||
mMockUIViewOperationQueue = new MockUIViewOperationQueue(reactContext);
|
||||
mFabricReconciler = new FabricReconciler(mMockUIViewOperationQueue);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,10 @@ package com.facebook.react.fabric;
|
|||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static com.facebook.react.bridge.InstanceHandleHelper.randomInstanceHandle;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.facebook.react.ReactRootView;
|
||||
import com.facebook.react.bridge.JavaScriptContextHolder;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactTestHelper;
|
||||
import com.facebook.react.bridge.ReadableNativeMap;
|
||||
|
@ -49,8 +51,8 @@ public class FabricUIManagerTest {
|
|||
Arrays.<ViewManager>asList(
|
||||
new ReactViewManager(), new ReactTextViewManager(), new ReactRawTextManager());
|
||||
ViewManagerRegistry viewManagerRegistry = new ViewManagerRegistry(viewManagers);
|
||||
|
||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry);
|
||||
JavaScriptContextHolder jsContext = mock(JavaScriptContextHolder.class);
|
||||
mFabricUIManager = new FabricUIManager(reactContext, viewManagerRegistry, jsContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue