Skip to content

Commit 72d0ddc

Browse files
JoshuaGrossfacebook-github-bot
authored andcommitted
Refactor Event to encourage and ease migration to RCTModernEventEmitter support
Summary: The `Event` interface has been improved such that: 1. `getEventData` is now a default method on Event that returns null 2. `dispatch` has a default implementation that relies on getEventName() and getEventData() 3. `dispatchModern` can detect if surfaceId and event data are present; if not, it falls back to dispatch This will dramatically ease future migrations: at some point in the (distant) future, we can simply delete RCTEventEmitter and all use-cases will be supported by the current `Event` class without needing to introduce a 3rd transitional interface; and 99% of all Event classes can be simplified, delet their `dispatch` implementation and need no further work. At their core, all Events are simply: (1) a name, (2) data, (3) a target (surfaceId and tag). The interface now reflects that but still allows for flexibility of the data and names being generated on-demand if necessary; but for the vast majority of Event classes, code will be dramatically simplified. I also migrate a single Event class, ContentSizeChangeEvent, to use this new method of dispatch. Changelog: [Android][Changed] Added convenience methods to simplify native Event classes and ease migrations Reviewed By: mdvacca Differential Revision: D26043325 fbshipit-source-id: bc308105f7f6e654d45fd156dbf4a2bcbc45819c
1 parent de8aa2c commit 72d0ddc

File tree

3 files changed

+58
-25
lines changed

3 files changed

+58
-25
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/events/ContentSizeChangeEvent.java

+8-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ public class ContentSizeChangeEvent extends Event<ContentSizeChangeEvent> {
1919
private final int mWidth;
2020
private final int mHeight;
2121

22+
@Deprecated
2223
public ContentSizeChangeEvent(int viewTag, int width, int height) {
23-
super(viewTag);
24+
this(-1, viewTag, width, height);
25+
}
26+
27+
public ContentSizeChangeEvent(int surfaceId, int viewTag, int width, int height) {
28+
super(surfaceId, viewTag);
2429
mWidth = width;
2530
mHeight = height;
2631
}
@@ -31,10 +36,10 @@ public String getEventName() {
3136
}
3237

3338
@Override
34-
public void dispatch(RCTEventEmitter rctEventEmitter) {
39+
protected WritableMap getEventData() {
3540
WritableMap data = Arguments.createMap();
3641
data.putDouble("width", PixelUtil.toDIPFromPixel(mWidth));
3742
data.putDouble("height", PixelUtil.toDIPFromPixel(mHeight));
38-
rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, data);
43+
return data;
3944
}
4045
}

ReactAndroid/src/main/java/com/facebook/react/uimanager/events/Event.java

+48-6
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,26 @@
77

88
package com.facebook.react.uimanager.events;
99

10+
import androidx.annotation.Nullable;
11+
import com.facebook.react.bridge.WritableMap;
1012
import com.facebook.react.common.SystemClock;
13+
import com.facebook.react.uimanager.IllegalViewOperationException;
1114

1215
/**
1316
* A UI event that can be dispatched to JS.
1417
*
15-
* <p>For dispatching events {@link EventDispatcher#dispatchEvent} should be used. Once event object
16-
* is passed to the EventDispatched it should no longer be used as EventDispatcher may decide to
17-
* recycle that object (by calling {@link #dispose}).
18+
* <p>For dispatching events {@code getEventData} should be used. Once event object is passed to the
19+
* EventDispatched it should no longer be used as EventDispatcher may decide to recycle that object
20+
* (by calling {@link #dispose}).
21+
*
22+
* <p>If you need advanced customizations and overriding only {@code getEventData} doesn't work for
23+
* you, you must override both {@code dispatch} and {@code dispatchModern}. Both of these will be
24+
* deleted in the distant future and it is highly recommended to use only {@code getEventData}.
25+
*
26+
* <p>Old, pre-Fabric Events only used viewTag as the identifier, but Fabric needs surfaceId as well
27+
* as viewTag. You may use {@code UIManagerHelper.getSurfaceId} on a Fabric-managed View to get the
28+
* surfaceId. Fabric will work without surfaceId - making {@code Event} backwards-compatible - but
29+
* Events without SurfaceId are slightly slower to propagate.
1830
*/
1931
public abstract class Event<T extends Event> {
2032

@@ -119,15 +131,45 @@ public void onDispose() {}
119131

120132
/**
121133
* Dispatch this event to JS using the given event emitter. Compatible with old and new renderer.
134+
* Instead of using this or dispatchModern, it is recommended that you simply override
135+
* `getEventData`. In the future
122136
*/
123137
@Deprecated
124-
public abstract void dispatch(RCTEventEmitter rctEventEmitter);
138+
public void dispatch(RCTEventEmitter rctEventEmitter) {
139+
WritableMap eventData = getEventData();
140+
if (eventData == null) {
141+
throw new IllegalViewOperationException(
142+
"Event: you must return a valid, non-null value from `getEventData`, or override `dispatch` and `disatchModern`. Event: "
143+
+ getEventName());
144+
}
145+
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), eventData);
146+
}
147+
148+
/**
149+
* Can be overridden by classes to make migrating to RCTModernEventEmitter support easier. If this
150+
* class returns null, the RCTEventEmitter interface will be used instead of
151+
* RCTModernEventEmitter. In the future, returning null here will be an error.
152+
*/
153+
@Nullable
154+
protected WritableMap getEventData() {
155+
return null;
156+
}
125157

126158
/**
127-
* Dispatch this event to JS using a V2 EventEmitter. Events must explicitly override this, by
128-
* default it uses the V1 dispatcher.
159+
* Dispatch this event to JS using a V2 EventEmitter. If surfaceId is not -1 and `getEventData` is
160+
* non-null, this will use the RCTModernEventEmitter API. Otherwise, it falls back to the
161+
* old-style dispatch function. For Event classes that need to do something different, this method
162+
* can always be overridden entirely, but it is not recommended.
129163
*/
164+
@Deprecated
130165
public void dispatchModern(RCTModernEventEmitter rctEventEmitter) {
166+
if (getSurfaceId() != -1) {
167+
WritableMap eventData = getEventData();
168+
if (eventData != null) {
169+
rctEventEmitter.receiveEvent(getSurfaceId(), getViewTag(), getEventName(), getEventData());
170+
return;
171+
}
172+
}
131173
dispatch(rctEventEmitter);
132174
}
133175
}

ReactAndroid/src/main/java/com/facebook/react/views/image/ImageLoadEvent.java

+2-16
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
import com.facebook.react.bridge.Arguments;
1313
import com.facebook.react.bridge.WritableMap;
1414
import com.facebook.react.uimanager.events.Event;
15-
import com.facebook.react.uimanager.events.RCTEventEmitter;
16-
import com.facebook.react.uimanager.events.RCTModernEventEmitter;
1715
import java.lang.annotation.Retention;
1816
import java.lang.annotation.RetentionPolicy;
1917

@@ -146,30 +144,18 @@ public short getCoalescingKey() {
146144
}
147145

148146
@Override
149-
public void dispatch(RCTEventEmitter rctEventEmitter) {
150-
rctEventEmitter.receiveEvent(getViewTag(), getEventName(), getEventData());
151-
}
152-
153-
@Override
154-
public void dispatchModern(RCTModernEventEmitter rctEventEmitter) {
155-
rctEventEmitter.receiveEvent(getSurfaceId(), getViewTag(), getEventName(), getEventData());
156-
}
157-
158-
private WritableMap getEventData() {
159-
WritableMap eventData = null;
147+
protected WritableMap getEventData() {
148+
WritableMap eventData = Arguments.createMap();
160149

161150
switch (mEventType) {
162151
case ON_PROGRESS:
163-
eventData = Arguments.createMap();
164152
eventData.putInt("loaded", mLoaded);
165153
eventData.putInt("total", mTotal);
166154
break;
167155
case ON_LOAD:
168-
eventData = Arguments.createMap();
169156
eventData.putMap("source", createEventDataSource());
170157
break;
171158
case ON_ERROR:
172-
eventData = Arguments.createMap();
173159
eventData.putString("error", mErrorMessage);
174160
break;
175161
}

0 commit comments

Comments
 (0)