Fix: Preserve native animated value after animated component unmount (#28841)

Summary:
After animation has been finished using Native driver there is no final value passed from the native to JS side. This causes a bug from https://github.com/facebook/react-native/issues/28114.

This PR solves this problem in the same way as `react-native-reanimated` library. When detaching it is calling native side to get the last value from Animated node and stores it on the JS side.

Preserving animated value even if animation was using `useNativeDriver: true`
Fixes https://github.com/facebook/react-native/issues/28114

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[Internal] [Fixed] - Save native Animated node value on JS side in detach phase
Pull Request resolved: https://github.com/facebook/react-native/pull/28841

Test Plan: Unit tests for added getValue method passed. Green CI

Reviewed By: mdvacca

Differential Revision: D22211499

Pulled By: JoshuaGross

fbshipit-source-id: 9a3a98a9f9a8536fe2c8764f667cdabe1f6ba82a
This commit is contained in:
TMaszko
2020-06-29 17:09:37 -07:00
committed by Facebook GitHub Bot
parent 0fda91ffff
commit d92284216f
16 changed files with 236 additions and 1 deletions
@@ -66,6 +66,9 @@ public abstract class NativeAnimatedModuleSpec extends ReactContextBaseJavaModul
public abstract void startAnimatingNode(double animationId, double nodeTag, ReadableMap config,
Callback endCallback);
@ReactMethod
public abstract void getValue(double tag, Callback saveValueCallback);
@ReactMethod
public abstract void stopListeningToAnimatedNodeValue(double tag);
@@ -186,6 +186,10 @@ namespace facebook {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, VoidKind, "createAnimatedNode", "(DLcom/facebook/react/bridge/ReadableMap;)V", args, count);
}
static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_getValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, VoidKind, "getValue", "(DLcom/facebook/react/bridge/Callback;)V", args, count);
}
static facebook::jsi::Value __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
return static_cast<JavaTurboModule&>(turboModule).invokeJavaMethod(rt, VoidKind, "startListeningToAnimatedNodeValue", "(D)V", args, count);
}
@@ -265,6 +269,9 @@ namespace facebook {
methodMap_["createAnimatedNode"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_createAnimatedNode};
methodMap_["getValue"] = MethodMetadata {2, __hostFunction_NativeAnimatedModuleSpecJSI_getValue};
methodMap_["startListeningToAnimatedNodeValue"] = MethodMetadata {1, __hostFunction_NativeAnimatedModuleSpecJSI_startListeningToAnimatedNodeValue};
@@ -774,4 +774,16 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
public void removeListeners(double count) {
// iOS only
}
@Override
public void getValue(final double animatedValueNodeTagDouble, final Callback callback) {
final int animatedValueNodeTag = (int) animatedValueNodeTagDouble;
mOperations.add(
new UIThreadOperation() {
@Override
public void execute(NativeAnimatedNodesManager animatedNodesManager) {
animatedNodesManager.getValue(animatedValueNodeTag, callback);
}
});
}
}
@@ -352,6 +352,15 @@ import java.util.Queue;
propsAnimatedNode.disconnectFromView(viewTag);
}
public void getValue(int tag, Callback callback) {
AnimatedNode node = mAnimatedNodes.get(tag);
if (node == null || !(node instanceof ValueAnimatedNode)) {
throw new JSApplicationIllegalArgumentException(
"Animated node with tag " + tag + " does not exists or is not a 'value' node");
}
callback.invoke(((ValueAnimatedNode) node).getValue());
}
public void restoreDefaultValues(int animatedNodeTag) {
AnimatedNode node = mAnimatedNodes.get(animatedNodeTag);
// Restoring default values needs to happen before UIManager operations so it is