Skip to content
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

fix: Run all animations on the same thread to prevent out of sync updates #6277

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

MatiPl01
Copy link
Member

@MatiPl01 MatiPl01 commented Jul 16, 2024

Summary

This PR changes the logic we use to execute animations. It executes all animations on the native thread instead of the UI and native thread to prevent animation synchronization issues. If at least one layout prop animation is detected in the batch, the whole animations batch is executed on the native thread.

It fixes the issue that can be seen only on paper. Fabric works fine as it uses its own logic.

Example recordings

Before After
Screen_Recording_20240717_185812_ReanimatedExample.mp4
Screen_Recording_20240717_185915_ReanimatedExample.mp4

Test plan

  • Open the empty example in the paper example app on android

Remarks

Performance impact must be assessed before merging this PR. It moves the execution of all updated to a single thread, which may not be that efficient compared to running updates on 2 threads (native and UI).

@MatiPl01 MatiPl01 self-assigned this Jul 16, 2024
@MatiPl01 MatiPl01 linked an issue Jul 16, 2024 that may be closed by this pull request
@@ -1,19 +1,131 @@
import { Text, StyleSheet, View } from 'react-native';
import type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will revert changes in this example file when we decide to merge this PR

@exzos28
Copy link

exzos28 commented Jul 19, 2024

Hi! I've faced crash issues using this patch and react-native-svg.
It looks like this:

java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@dc5283f
    at android.graphics.BaseCanvas.throwIfCannotDraw(BaseCanvas.java:66)
    at android.graphics.MiuiCanvas.throwIfCannotDraw(MiuiCanvas.java:329)
    at android.graphics.RecordingCanvas.throwIfCannotDraw(RecordingCanvas.java:277)
    at android.graphics.BaseRecordingCanvas.drawBitmap(BaseRecordingCanvas.java:69)
    at com.horcrux.svg.SvgView.onDraw(SvgView.java:133)
    at android.view.View.draw(View.java:21668)
    at android.view.View.updateDisplayListIfDirty(View.java:20503)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4461)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4434)
    at android.view.View.updateDisplayListIfDirty(View.java:20454)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:575)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:581)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:654)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:3858)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3649)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2969)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1869)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8024)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:969)
    at android.view.Choreographer.doCallbacks(Choreographer.java:793)
    at android.view.Choreographer.doFrame(Choreographer.java:728)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:954)

Do you have any idea?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

withRepeat is flickering on android
2 participants