- 
          
 - 
                Notifications
    
You must be signed in to change notification settings  - Fork 1.4k
 
fix(android): fix bug w/ LA where animation never executed when scheduled from JS #8450
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
base: main
Are you sure you want to change the base?
fix(android): fix bug w/ LA where animation never executed when scheduled from JS #8450
Conversation
| 
           I'll dare to ping @bartlomiejbloniarz as you introduced the change :p  | 
    
| 
           Oh, also a second consideration. In case we continue over a mutation: Lines 418 to 424 in 794a669 
 At the end of  Line 444 in 794a669 
 I was wondering: don't we need to keep the update for the view we were skipping?  | 
    
| 
           I just tested, and applying this change on top of 3.19.3 in the reproduction of this issue: does not fix the issue. However, it certainly fixed the issue in our clients app.  | 
    
| 
           RFC to remove the ui thread check in rn core:  | 
    
| 
           Hi @hannojg 👋 Thanks for the PR, I think we could merge it as it is, but I don't fully understand how the issue happens. When the  Did you see why the updates are not applied/triggered? Because maybe there is a flow that's worth fixing before we allow for this check on the JS thread. The reason I'm not sure about it, is that calling this check from the JS thread, doesn't guarantee us that the view is currently mounted, when the transaction is actually applied on the main thread. So I want to avoid changes here if I can.  | 
    
Summary
To my shame, i believe there is no issue for this yet and i also didn't create a reproduction (yet) 🥶
The issue:
There is a bug with
layoutanimations where they don't seem to fire. Effects of this are:layoutanimation, and staying "stuck" on the screenI have the hunch that it could for example fix this issue (will test tmrw):[Android] Reanimated entering/exiting animations not working properly #8445The issue started happening after upgrading from
3.17.4to3.19.3, which includes this change:The cause:
The mentioned change was introduced to circumvent this bug:
I believe the change introduced a regression where a layout animation might not run at all:
NativeProxy.preserveMountedTagswould returnfalsewhen we are not on the UI thread, which is the case ifpullTransactionis called from the JS threadNativeProxy::preserveMountedTagswill return an empty optionalLayoutAnimationsProxy::addOngoingAnimationswill return as the vector is empty:react-native-reanimated/packages/react-native-reanimated/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp
Lines 404 to 406 in 794a669
The fix:
When you look into
FabricUIManager.resolveView(tag)it hasUIThreadUtils.assertOnUIThread(), which looks problematic.However, if you check all the data structures that are being used, all of them are
ConcurrentHashMaps, so I thinkresolveViewis actually thread safe:Thus i removed the check if we are on the UI thread, and hence
addOngoingAnimation()will execute, even if invoked from the JS thread.I will make a RFC in react-native to remove the UIThread check there since i think its not needed.
Alternatively I was thinking of two other ways:
FabricUIManageradd a new thread safegetViewExistsmethod (since in SurfaceMountingManager this method isn't marked as UI thread specific)ShadowViewsto track in which revision they've been created. Then we can listen to theshadowTreeDidMounthook to capture the latest mounted revision and check if the tag/ shadowView we want to animate is equal or lower to that latest mounted revision. This way we would also avoid the JNI call.Test plan
I tested all the LA tests from the fabric-example app.
Note
I might completely have missed a good reason why we only ever want to run that code on the UI thread. But as i checked, before we also were okay with executing it from the JS thread, we just wanted to avoid running it on not yet mounted views.