-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement native Animated value listeners on Android #8844
Implement native Animated value listeners on Android #8844
Conversation
|
||
componentWillUnmount() { | ||
this.state.anim.removeAllListeners(); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
property current
Property not found in React component
Looks good to me. For sending events to JS you should use a subclass of |
@kmagiera EventDispatcher seems pretty coupled with component events. It would require quite a bit of refactoring to be able to dispatch events for a native module. I looked at it a bit and every native module seems to call directly into RCTDeviceEventEmitter. But I agree that being able to coalesce these event especially when JS thread is busy it would be nice not to queue up an event for every frame. I actually had to implement a similar logic for requestIdleCallback recently so having some generic way to coalesce events from native modules would be great like we have for native components. |
5da9576
to
d2fd849
Compare
Ah ok, I see now that EventDispatcher sends events to RCTEventEmitter and here you want to deliver them to RCTDeviceEventEmitter. Although, so far we haven't been using RCTDeviceEventEmitter for sending events that could be coalesced (e.g. keyboard show/hide, passing network data, app state changes). So I think we should at least create an issue to refactor EventDispatcher to support device events and to use it here. |
@kmagiera - once that issue is created is this good to ship? cc @janicduplessis |
@@ -1199,11 +1243,9 @@ class AnimatedStyle extends AnimatedWithChildren { | |||
for (var key in this._style) { | |||
var value = this._style[key]; | |||
if (value instanceof Animated) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't we going to have a problem if we happen to re-render during an animation? Namely, out-of-date JS values will override up-to-date native values when the view us updated. Contrived example:
Tick 1 (first render):
- js=0
- native=0
Tick 2 (animation driven natively):
- js=0
- native=0.1
Tick 3: (still driving, listener called on the JS side)
- js=0.1
- native=0.2
Tick 4: (still driving, we call a re-render)
- js=0.2
- native=0.3
Tick 5 (re-rendered):
- js=0.2
- native=0.2 (but we'd expect 0.4)
It seems like the old __getValue
, this updated __getValue
behavior, and __getAnimatedValue
all have slightly different intents:
(1) What prop values should we be setting on the native view when we render?
(2) What are the current values of animated props?
(3) What values are we driving and may need update via setNativeProps? (inverse of 1)
It seems like there is a great tension between an animate prop being treated like any other prop, and being managed independently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not see this as an issue. It's similar with all the events we receive from native. E.g. when you register onLayout event it doesn't necessarily mean the values you're getting are the actual dimensions of the element, those are just values that has been calculated during some layout pass in the past and might have already been changed from JS before we managed to process onLayout event
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine that the values passed to JS aren't representative of the true state of the element. What's not okay is if we take this stale data and use it to update the element, which we will do here whenever we render the element again. Concretely, you might see the animated view unexpectedly snap backward in time when you call setState, which would be jarring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll take another look at this to make sure it doesn't cause issues when re-rendering during an animation when there is no value listener. It did work properly when using one since we update the js value of the node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another contrived example, but imagine there is no value listener and you do the following:
- render a view with opacity = new Animated.Value(0)
- call anim.setValue(1)
- drive a native animation from 1 to 0.5
- call setState({foo: 'bar'}); the view will be re-rendered with opacity=1
The bug will pop up when both the following conditions are true:
- the value has changed on the JS side since the last render
- the value on the JS side and the native side are out of sync
@brentvatne Yes, I believe this is good to be merged. Just would prefer someone who is more actively maintaining this piece of code to merge this in :) |
d2fd849
to
4ded7e0
Compare
@janicduplessis updated the pull request. |
4ded7e0
to
4a84fa0
Compare
@janicduplessis updated the pull request. |
4a84fa0
to
b140818
Compare
@janicduplessis updated the pull request. |
@ryangomba You were right about issues with removing the __isNative checks so I went ahead and used your solution from #9120 and just changed the condition to |
This should be good to go now. @kmagiera You're probably still the one that knows the most about this code so feel free to shipit :) |
I'll ship this tomorrow if kmagiera isn't able to get around to it. |
@facebook-github-bot shipit |
Thanks for importing.If you are an FB employee go to Phabricator to review internal test results. |
158d435
Summary: Adds support for `Animated.Value#addListener` for native driven nodes on Android. This is based on work by skevy in the exponent RN fork. Also adds a UIExplorer example. ** Test plan ** Run unit tests Tested that by adding a listener to a native driven animated node and checked that the listener callback is called properly. Also tested that it doesn't crash on iOS that doesn't support this yet. Closes facebook/react-native#8844 Differential Revision: D3670906 fbshipit-source-id: 15700ed7b93db140d907ce80af4dae6be3102135
Summary: Adds support for `Animated.Value#addListener` for native driven animated values. Same as #8844 but for iOS. This depends on some JS code in #8844 so only review the 2nd commit and let's wait for #8844 to land first. **Test plan** Tested using the UIExplorer example. Closes #9194 Differential Revision: D3681749 fbshipit-source-id: 521a61e2221c1ad1f6f40c75dd2dc957361d0271
Summary: Adds support for `Animated.Value#addListener` for native driven nodes on Android. This is based on work by skevy in the exponent RN fork. Also adds a UIExplorer example. ** Test plan ** Run unit tests Tested that by adding a listener to a native driven animated node and checked that the listener callback is called properly. Also tested that it doesn't crash on iOS that doesn't support this yet. Closes facebook#8844 Differential Revision: D3670906 fbshipit-source-id: 15700ed7b93db140d907ce80af4dae6be3102135
Summary: Adds support for `Animated.Value#addListener` for native driven animated values. Same as facebook#8844 but for iOS. This depends on some JS code in facebook#8844 so only review the 2nd commit and let's wait for facebook#8844 to land first. **Test plan** Tested using the UIExplorer example. Closes facebook#9194 Differential Revision: D3681749 fbshipit-source-id: 521a61e2221c1ad1f6f40c75dd2dc957361d0271
Adds support for
Animated.Value#addListener
for native driven nodes on Android. This is based on work by @skevy in the exponent RN fork. Also adds a UIExplorer example.** Test plan **
Run unit tests
Tested that by adding a listener to a native driven animated node and checked that the listener callback is called properly.
Also tested that it doesn't crash on iOS that doesn't support this yet.