Refactor setup of Event Dispatcher

Reviewed By: achen1

Differential Revision: D7746311

fbshipit-source-id: cfee1c2ced6d85477628085f3260496e80ae48c2
This commit is contained in:
David Vacca
2018-05-30 21:48:52 -07:00
committed by Facebook Github Bot
parent e61341ba32
commit 58ea20b5e8
9 changed files with 126 additions and 50 deletions

View File

@@ -7,11 +7,12 @@
package com.facebook.react.testing; package com.facebook.react.testing;
import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.FrameLayout; import android.widget.FrameLayout;
@@ -38,7 +39,7 @@ import com.facebook.react.testing.idledetection.ReactIdleDetectionUtil;
import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.ViewManagerRegistry; import com.facebook.react.uimanager.ViewManagerRegistry;
import java.util.ArrayList; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -244,35 +245,28 @@ public class ReactAppTestActivity extends FragmentActivity
.setBridgeIdleDebugListener(mBridgeIdleSignaler) .setBridgeIdleDebugListener(mBridgeIdleSignaler)
.setInitialLifecycleState(mLifecycleState) .setInitialLifecycleState(mLifecycleState)
.setJSIModulesProvider( .setJSIModulesProvider(
new JSIModulesProvider() { new JSIModulesProvider() {
@Override @Override
public List<JSIModuleHolder> getJSIModules( public List<JSIModuleHolder> getJSIModules(
final ReactApplicationContext reactApplicationContext, final ReactApplicationContext reactApplicationContext,
final JavaScriptContextHolder jsContext) { final JavaScriptContextHolder jsContext) {
return Arrays.<JSIModuleHolder>asList(new JSIModuleHolder() {
@Override
public Class<? extends JSIModule> getJSIModuleClass() {
return UIManager.class;
}
List<JSIModuleHolder> modules = new ArrayList<>(); @Override
modules.add( public FabricUIManager getJSIModule() {
new JSIModuleHolder() { List<ViewManager> viewManagers =
mReactInstanceManager.getOrCreateViewManagers(reactApplicationContext);
@Override FabricUIManager fabricUIManager =
public Class<? extends JSIModule> getJSIModuleClass() { new FabricUIManager(reactApplicationContext, new ViewManagerRegistry(viewManagers));
return UIManager.class; new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
} return fabricUIManager;
}
@Override });
public FabricUIManager getJSIModule() { }})
List<ViewManager> viewManagers =
getReactInstanceManager().getOrCreateViewManagers(reactApplicationContext);
FabricUIManager fabricUIManager =
new FabricUIManager(
reactApplicationContext, new ViewManagerRegistry(viewManagers));
new FabricJSCBinding().installFabric(jsContext, fabricUIManager);
return fabricUIManager;
}
});
return modules;
}})
.setUIImplementationProvider(uiImplementationProvider); .setUIImplementationProvider(uiImplementationProvider);
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);

View File

@@ -82,6 +82,7 @@ import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.UIImplementationProvider; import com.facebook.react.uimanager.UIImplementationProvider;
import com.facebook.react.uimanager.UIManagerHelper; import com.facebook.react.uimanager.UIManagerHelper;
import com.facebook.react.uimanager.ViewManager; import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper; import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
import com.facebook.soloader.SoLoader; import com.facebook.soloader.SoLoader;
import com.facebook.systrace.Systrace; import com.facebook.systrace.Systrace;
@@ -1077,6 +1078,8 @@ public class ReactInstanceManager {
ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName()); ReactMarker.logMarker(CREATE_REACT_CONTEXT_START, jsExecutor.getName());
final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext); final ReactApplicationContext reactContext = new ReactApplicationContext(mApplicationContext);
reactContext.setEventDispatcher(new EventDispatcher(reactContext));
NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null NativeModuleCallExceptionHandler exceptionHandler = mNativeModuleCallExceptionHandler != null
? mNativeModuleCallExceptionHandler ? mNativeModuleCallExceptionHandler
: mDevSupportManager; : mDevSupportManager;

View File

@@ -0,0 +1,13 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.bridge;
/**
* Marker interface for EventDispatcher.
*/
public interface EventDispatcher {
}

View File

@@ -39,6 +39,7 @@ public class ReactContext extends ContextWrapper {
private LifecycleState mLifecycleState = LifecycleState.BEFORE_CREATE; private LifecycleState mLifecycleState = LifecycleState.BEFORE_CREATE;
private @Nullable EventDispatcher mEventDispatcher;
private @Nullable CatalystInstance mCatalystInstance; private @Nullable CatalystInstance mCatalystInstance;
private @Nullable LayoutInflater mInflater; private @Nullable LayoutInflater mInflater;
private @Nullable MessageQueueThread mUiMessageQueueThread; private @Nullable MessageQueueThread mUiMessageQueueThread;
@@ -349,4 +350,12 @@ public class ReactContext extends ContextWrapper {
public JavaScriptContextHolder getJavaScriptContextHolder() { public JavaScriptContextHolder getJavaScriptContextHolder() {
return mCatalystInstance.getJavaScriptContextHolder(); return mCatalystInstance.getJavaScriptContextHolder();
} }
public <T extends EventDispatcher> T getEventDispatcher() {
return (T) mEventDispatcher;
}
public void setEventDispatcher(EventDispatcher eventDispatcher) {
mEventDispatcher = eventDispatcher;
}
} }

View File

@@ -22,6 +22,7 @@ public class Scheduler {
public void scheduleWork(Work work) { public void scheduleWork(Work work) {
// TODO T26717866 this method needs to be implemented. The current implementation is just for // TODO T26717866 this method needs to be implemented. The current implementation is just for
// testing purpose. // testing purpose.
work.run(); work.run();
} }

View File

@@ -9,12 +9,11 @@ package com.facebook.react.uimanager;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_END; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_END;
import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START; import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_CONSTANTS_START;
import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT; import static com.facebook.react.uimanager.common.UIManagerType.DEFAULT;
import android.content.ComponentCallbacks2; import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration;
import android.media.AudioManager; import android.media.AudioManager;
import com.facebook.common.logging.FLog; import com.facebook.common.logging.FLog;
import com.facebook.debug.holder.PrinterHolder; import com.facebook.debug.holder.PrinterHolder;
@@ -42,6 +41,7 @@ import com.facebook.react.uimanager.common.SizeMonitoringFrameLayout;
import com.facebook.react.uimanager.common.ViewUtil; import com.facebook.react.uimanager.common.ViewUtil;
import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener; import com.facebook.react.uimanager.debug.NotThreadSafeViewHierarchyUpdateDebugListener;
import com.facebook.react.uimanager.events.EventDispatcher; import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.facebook.systrace.Systrace; import com.facebook.systrace.Systrace;
import com.facebook.systrace.SystraceMessage; import com.facebook.systrace.SystraceMessage;
import java.util.ArrayList; import java.util.ArrayList;
@@ -129,7 +129,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
int minTimeLeftInFrameForNonBatchedOperationMs) { int minTimeLeftInFrameForNonBatchedOperationMs) {
super(reactContext); super(reactContext);
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
mEventDispatcher = new EventDispatcher(reactContext); mEventDispatcher = reactContext.getEventDispatcher();
mModuleConstants = createConstants(viewManagerResolver); mModuleConstants = createConstants(viewManagerResolver);
mCustomDirectEvents = UIManagerModuleConstants.getDirectEventTypeConstants(); mCustomDirectEvents = UIManagerModuleConstants.getDirectEventTypeConstants();
mUIImplementation = mUIImplementation =
@@ -149,7 +149,7 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
int minTimeLeftInFrameForNonBatchedOperationMs) { int minTimeLeftInFrameForNonBatchedOperationMs) {
super(reactContext); super(reactContext);
DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext); DisplayMetricsHolder.initDisplayMetricsIfNotInitialized(reactContext);
mEventDispatcher = new EventDispatcher(reactContext); mEventDispatcher = reactContext.getEventDispatcher();
mCustomDirectEvents = MapBuilder.newHashMap(); mCustomDirectEvents = MapBuilder.newHashMap();
mModuleConstants = createConstants(viewManagersList, null, mCustomDirectEvents); mModuleConstants = createConstants(viewManagersList, null, mCustomDirectEvents);
mUIImplementation = mUIImplementation =
@@ -182,10 +182,14 @@ public class UIManagerModule extends ReactContextBaseJavaModule implements
@Override @Override
public void initialize() { public void initialize() {
getReactApplicationContext().registerComponentCallbacks(mMemoryTrimCallback); getReactApplicationContext().registerComponentCallbacks(mMemoryTrimCallback);
mEventDispatcher.registerEventEmitter(
DEFAULT,
getReactApplicationContext().getJSModule(RCTEventEmitter.class));
} }
@Override @Override
public void onHostResume() { public void onHostResume() {
mUIImplementation.onHostResume(); mUIImplementation.onHostResume();
} }

View File

@@ -7,16 +7,7 @@
package com.facebook.react.uimanager.events; package com.facebook.react.uimanager.events;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.LifecycleEventListener;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
@@ -26,6 +17,12 @@ import com.facebook.react.modules.core.ChoreographerCompat;
import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.modules.core.ReactChoreographer;
import com.facebook.react.uimanager.common.UIManagerType; import com.facebook.react.uimanager.common.UIManagerType;
import com.facebook.systrace.Systrace; import com.facebook.systrace.Systrace;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
/** /**
* Class responsible for dispatching UI events to JS. The main purpose of this class is to act as an * Class responsible for dispatching UI events to JS. The main purpose of this class is to act as an
@@ -59,7 +56,8 @@ import com.facebook.systrace.Systrace;
* EVENT_TYPE_ID_MASK = 0x0000ffff00000000 * EVENT_TYPE_ID_MASK = 0x0000ffff00000000
* COALESCING_KEY_MASK = 0xffff000000000000 * COALESCING_KEY_MASK = 0xffff000000000000
*/ */
public class EventDispatcher implements LifecycleEventListener { public class EventDispatcher implements LifecycleEventListener,
com.facebook.react.bridge.EventDispatcher {
private static final Comparator<Event> EVENT_COMPARATOR = new Comparator<Event>() { private static final Comparator<Event> EVENT_COMPARATOR = new Comparator<Event>() {
@Override @Override
@@ -99,7 +97,7 @@ public class EventDispatcher implements LifecycleEventListener {
private Event[] mEventsToDispatch = new Event[16]; private Event[] mEventsToDispatch = new Event[16];
private int mEventsToDispatchSize = 0; private int mEventsToDispatchSize = 0;
private volatile @Nullable RCTEventEmitter mRCTEventEmitter; private volatile @Nullable ReactEventEmitter mRCTEventEmitter = new ReactEventEmitter();
private short mNextEventTypeId = 0; private short mNextEventTypeId = 0;
private volatile boolean mHasDispatchScheduled = false; private volatile boolean mHasDispatchScheduled = false;
@@ -153,9 +151,6 @@ public class EventDispatcher implements LifecycleEventListener {
@Override @Override
public void onHostResume() { public void onHostResume() {
if (mRCTEventEmitter == null) {
mRCTEventEmitter = mReactContext.getJSModule(RCTEventEmitter.class);
}
mCurrentFrameCallback.maybePostFromNonUI(); mCurrentFrameCallback.maybePostFromNonUI();
} }
@@ -255,6 +250,10 @@ public class EventDispatcher implements LifecycleEventListener {
(((long) coalescingKey) & 0xffff) << 48; (((long) coalescingKey) & 0xffff) << 48;
} }
public void registerEventEmitter(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter) {
mRCTEventEmitter.register(uiManagerType, eventEmitter);
}
private class ScheduleDispatchFrameCallback extends ChoreographerCompat.FrameCallback { private class ScheduleDispatchFrameCallback extends ChoreographerCompat.FrameCallback {
private volatile boolean mIsPosted = false; private volatile boolean mIsPosted = false;
private boolean mShouldStop = false; private boolean mShouldStop = false;

View File

@@ -14,8 +14,8 @@ import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
public interface RCTEventEmitter extends JavaScriptModule { public interface RCTEventEmitter extends JavaScriptModule {
public void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event); void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event);
public void receiveTouches( void receiveTouches(
String eventName, String eventName,
WritableArray touches, WritableArray touches,
WritableArray changedIndices); WritableArray changedIndices);

View File

@@ -0,0 +1,53 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.uimanager.events;
import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_KEY;
import android.util.SparseArray;
import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.uimanager.common.UIManagerType;
import com.facebook.react.uimanager.common.ViewUtil;
import javax.annotation.Nullable;
public class ReactEventEmitter implements RCTEventEmitter {
private final SparseArray<RCTEventEmitter> mEventEmitters = new SparseArray<>();
public ReactEventEmitter() {
}
public void register(@UIManagerType int uiManagerType, RCTEventEmitter eventEmitter) {
mEventEmitters.put(uiManagerType, eventEmitter);
}
@Override
public void receiveEvent(int targetReactTag, String eventName, @Nullable WritableMap event) {
getEventEmitter(targetReactTag).receiveEvent(targetReactTag, eventName, event);
}
@Override
public void receiveTouches(
String eventName,
WritableArray touches,
WritableArray changedIndices) {
Assertions.assertCondition(touches.size() > 0);
int targetReactTag = touches.getMap(0).getInt(TARGET_KEY);
getEventEmitter(targetReactTag).receiveTouches(eventName, touches, changedIndices);
}
private RCTEventEmitter getEventEmitter(int reactTag) {
int type = ViewUtil.getUIManagerType(reactTag);
return mEventEmitters.get(type);
}
}