Skip to content

Commit 565a743

Browse files
lunaleapsfacebook-github-bot
authored andcommitted
Refactor EventDriverAnimations to customize event match
Summary: Changelog: [Internal] - Refactor match logic on determining whether to run an EventAnimationDriver (drivers for natively animated events) for an Event dispatched. Previously, drivers were stored by key on the NativeAnimatedNodesManager (based on event handler and viewTag) and has been refactored to be stored in a list for easier matching. This diff changes it so the match logic for running an EventAnimationDriver happens on the Event instance. This change is motivated by PointerEvents needing custom match logic (done on a following change). Reviewed By: javache Differential Revision: D40691002 fbshipit-source-id: e4f6742a2af3b751214aefa1fc069f65e8e71d77
1 parent c565a77 commit 565a743

File tree

3 files changed

+67
-39
lines changed

3 files changed

+67
-39
lines changed

ReactAndroid/src/main/java/com/facebook/react/animated/EventAnimationDriver.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,13 @@
2121
/* package */ class EventAnimationDriver implements RCTEventEmitter {
2222
private List<String> mEventPath;
2323
/* package */ ValueAnimatedNode mValueNode;
24+
/* package */ String mEventName;
25+
/* package */ int mViewTag;
2426

25-
public EventAnimationDriver(List<String> eventPath, ValueAnimatedNode valueNode) {
27+
public EventAnimationDriver(
28+
String eventName, int viewTag, List<String> eventPath, ValueAnimatedNode valueNode) {
29+
mEventName = eventName;
30+
mViewTag = viewTag;
2631
mEventPath = eventPath;
2732
mValueNode = valueNode;
2833
}

ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedNodesManager.java

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,9 @@
3131
import com.facebook.react.uimanager.events.EventDispatcherListener;
3232
import java.util.ArrayDeque;
3333
import java.util.ArrayList;
34-
import java.util.HashMap;
3534
import java.util.LinkedList;
3635
import java.util.List;
3736
import java.util.ListIterator;
38-
import java.util.Map;
3937
import java.util.Queue;
4038

4139
/**
@@ -58,9 +56,9 @@ public class NativeAnimatedNodesManager implements EventDispatcherListener {
5856
private final SparseArray<AnimatedNode> mAnimatedNodes = new SparseArray<>();
5957
private final SparseArray<AnimationDriver> mActiveAnimations = new SparseArray<>();
6058
private final SparseArray<AnimatedNode> mUpdatedNodes = new SparseArray<>();
61-
// Mapping of a view tag and an event name to a list of event animation drivers. 99% of the time
62-
// there will be only one driver per mapping so all code code should be optimized around that.
63-
private final Map<String, List<EventAnimationDriver>> mEventDrivers = new HashMap<>();
59+
// List of event animation drivers for an event on view.
60+
// There may be multiple drivers for the same event and view.
61+
private final List<EventAnimationDriver> mEventDrivers = new ArrayList<>();
6462
private final ReactApplicationContext mReactApplicationContext;
6563
private int mAnimatedGraphBFSColor = 0;
6664
// Used to avoid allocating a new array on every frame in `runUpdates` and `onEventDispatch`.
@@ -501,7 +499,8 @@ public void restoreDefaultValues(int animatedNodeTag) {
501499
}
502500

503501
@UiThread
504-
public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap eventMapping) {
502+
public void addAnimatedEventToView(
503+
int viewTag, String eventHandlerName, ReadableMap eventMapping) {
505504
int nodeTag = eventMapping.getInt("animatedValueTag");
506505
AnimatedNode node = mAnimatedNodes.get(nodeTag);
507506
if (node == null) {
@@ -512,8 +511,8 @@ public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap ev
512511
throw new JSApplicationIllegalArgumentException(
513512
"addAnimatedEventToView: Animated node on view ["
514513
+ viewTag
515-
+ "] connected to event ("
516-
+ eventName
514+
+ "] connected to event handler ("
515+
+ eventHandlerName
517516
+ ") should be of type "
518517
+ ValueAnimatedNode.class.getName());
519518
}
@@ -524,32 +523,27 @@ public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap ev
524523
pathList.add(path.getString(i));
525524
}
526525

527-
EventAnimationDriver event = new EventAnimationDriver(pathList, (ValueAnimatedNode) node);
528-
String key = viewTag + eventName;
529-
if (mEventDrivers.containsKey(key)) {
530-
mEventDrivers.get(key).add(event);
531-
} else {
532-
List<EventAnimationDriver> drivers = new ArrayList<>(1);
533-
drivers.add(event);
534-
mEventDrivers.put(key, drivers);
535-
}
526+
String eventName = normalizeEventName(eventHandlerName);
527+
528+
EventAnimationDriver eventDriver =
529+
new EventAnimationDriver(eventName, viewTag, pathList, (ValueAnimatedNode) node);
530+
mEventDrivers.add(eventDriver);
536531
}
537532

538533
@UiThread
539-
public void removeAnimatedEventFromView(int viewTag, String eventName, int animatedValueTag) {
540-
String key = viewTag + eventName;
541-
if (mEventDrivers.containsKey(key)) {
542-
List<EventAnimationDriver> driversForKey = mEventDrivers.get(key);
543-
if (driversForKey.size() == 1) {
544-
mEventDrivers.remove(viewTag + eventName);
545-
} else {
546-
ListIterator<EventAnimationDriver> it = driversForKey.listIterator();
547-
while (it.hasNext()) {
548-
if (it.next().mValueNode.mTag == animatedValueTag) {
549-
it.remove();
550-
break;
551-
}
552-
}
534+
public void removeAnimatedEventFromView(
535+
int viewTag, String eventHandlerName, int animatedValueTag) {
536+
537+
String eventName = normalizeEventName(eventHandlerName);
538+
539+
ListIterator<EventAnimationDriver> it = mEventDrivers.listIterator();
540+
while (it.hasNext()) {
541+
EventAnimationDriver driver = it.next();
542+
if (eventName.equals(driver.mEventName)
543+
&& viewTag == driver.mViewTag
544+
&& animatedValueTag == driver.mValueNode.mTag) {
545+
it.remove();
546+
break;
553547
}
554548
}
555549
}
@@ -585,18 +579,19 @@ private void handleEvent(Event event) {
585579
if (uiManager == null) {
586580
return;
587581
}
588-
String eventName = uiManager.resolveCustomDirectEventName(event.getEventName());
589-
if (eventName == null) {
590-
eventName = "";
591-
}
592582

593-
List<EventAnimationDriver> driversForKey = mEventDrivers.get(event.getViewTag() + eventName);
594-
if (driversForKey != null) {
595-
for (EventAnimationDriver driver : driversForKey) {
583+
boolean foundAtLeastOneDriver = false;
584+
Event.EventAnimationDriverMatchSpec matchSpec = event.getEventAnimationDriverMatchSpec();
585+
for (EventAnimationDriver driver : mEventDrivers) {
586+
if (matchSpec.match(driver.mViewTag, driver.mEventName)) {
587+
foundAtLeastOneDriver = true;
596588
stopAnimationsForNode(driver.mValueNode);
597589
event.dispatch(driver);
598590
mRunUpdateNodeList.add(driver.mValueNode);
599591
}
592+
}
593+
594+
if (foundAtLeastOneDriver) {
600595
updateNodes(mRunUpdateNodeList);
601596
mRunUpdateNodeList.clear();
602597
}
@@ -824,4 +819,14 @@ private void updateNodes(List<AnimatedNode> nodes) {
824819
mWarnedAboutGraphTraversal = false;
825820
}
826821
}
822+
823+
private String normalizeEventName(String eventHandlerName) {
824+
// Fabric UIManager also makes this assumption
825+
String eventName = eventHandlerName;
826+
if (eventHandlerName.startsWith("on")) {
827+
eventName = "top" + eventHandlerName.substring(2);
828+
}
829+
830+
return eventName;
831+
}
827832
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public abstract class Event<T extends Event> {
4040
private int mViewTag;
4141
private long mTimestampMs;
4242
private int mUniqueID = sUniqueID++;
43+
private @Nullable EventAnimationDriverMatchSpec mEventAnimationDriverMatchSpec;
4344

4445
protected Event() {}
4546

@@ -165,6 +166,19 @@ public void onDispose() {}
165166
/** @return the name of this event as registered in JS */
166167
public abstract String getEventName();
167168

169+
public EventAnimationDriverMatchSpec getEventAnimationDriverMatchSpec() {
170+
if (mEventAnimationDriverMatchSpec == null) {
171+
mEventAnimationDriverMatchSpec =
172+
new EventAnimationDriverMatchSpec() {
173+
@Override
174+
public boolean match(int viewTag, String eventName) {
175+
return viewTag == getViewTag() && eventName.equals(getEventName());
176+
};
177+
};
178+
}
179+
return mEventAnimationDriverMatchSpec;
180+
}
181+
168182
/**
169183
* Dispatch this event to JS using the given event emitter. Compatible with old and new renderer.
170184
* Instead of using this or dispatchModern, it is recommended that you simply override
@@ -225,4 +239,8 @@ public void dispatchModern(RCTModernEventEmitter rctEventEmitter) {
225239
}
226240
dispatch(rctEventEmitter);
227241
}
242+
243+
public interface EventAnimationDriverMatchSpec {
244+
boolean match(int viewTag, String eventName);
245+
}
228246
}

0 commit comments

Comments
 (0)