rive-app / rive-android

A runtime for interactive animations on Android
https://rive.app
MIT License
350 stars 31 forks source link

'Has no surface' when using Rive in Compose #279

Closed PhilippNowak96 closed 1 year ago

PhilippNowak96 commented 1 year ago

Description

When using Rive as part of an AndroidView in Compose we currently experience log spam of

2022-12-16 13:56:22.630 2490-3218/xxx E/src/models/jni_renderer_skia.cpp:163: Has No Surface!

until we leave the screen containing the animation. Beside possible performance issues, which we are not aware of right now, there are no other issues. Animations work as expected.

Provide a Repro

The following code snippet should reproduce the issue:

@Composable
fun CustomRiveAnimationView(
    modifier: Modifier = Modifier,
    @RawRes animation: Int,
    stateMachineName: String? = null,
    alignment: Alignment = Alignment.CENTER
) {
    AndroidView(
        modifier = modifier,
        factory = { context ->
            RiveAnimationView(context).also {
                it.setRiveResource(
                    resId = animation,
                    stateMachineName = stateMachineName,
                    alignment = alignment
                )
            }
        }
    )
}

Expected behavior

Log isn't spammed -> no error occurs

Device & Versions (please complete the following information)

chanjungkim commented 1 year ago

Is it solved?

PhilippNowak96 commented 1 year ago

No it isn't. We also experienced that it only happens when the RiveAnimationView is currently not in the visible region (e.g. scrolled away etc.)

DominikCsokas commented 1 year ago

The same error message appears when I use it on a ViewPager item. Especially when I step back to a previous item.

umberto-sonnino commented 1 year ago

Hi @PhilippNowak96! I tried copy-pasting your snippet into the basic Empty Compose Activity generated via Android Studio and it's currently behaving as expected with the riv files available in the example like so:

class ComposeActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            // A surface container using the 'background' color from the theme
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colorScheme.background
            ) {
                CustomRiveAnimationView(animation = R.raw.basketball)
            }
        }
    }
}

Since your report is from 4.2.1 and we're currently at 4.3.2, would you mind trying it on the latest version? One of our latest patches might've fixed this

PhilippNowak96 commented 1 year ago

Hi @umberto-sonnino, thanks for looking into this!

At first: I guess my initial post missed a detail which the later comments included already: You need to get the RiveAnimationView outside of the displayed content. That wasn't clear to me when I initially created the post and somehow seemed to be the case when I created and tested the repro snippet. Sorry for that!

So the actual repro for example using the Accompanist HorizontalPager could look like this:

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalPagerApi::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            RiveAndroidCrashTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    HorizontalPager(count = 3) {
                        if (it == 0) {
                            CustomRiveAnimationView(
                                animation = R.raw.survey,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .requiredHeight(200.dp)
                            )
                        } else {
                            Text("Page: $it")
                        }
                    }
                }
            }
        }
    }

    @Composable
    fun CustomRiveAnimationView(
        modifier: Modifier = Modifier,
        @RawRes animation: Int,
        stateMachineName: String? = null,
        alignment: Alignment = Alignment.CENTER,
    ) {
        AndroidView(
            modifier = modifier,
            factory = { context ->
                RiveAnimationView(context).also {
                    it.setRiveResource(
                        resId = animation,
                        stateMachineName = stateMachineName,
                        alignment = alignment,
                    )
                }
            }
        )
    }
}

But as you mentioned this repro was for 4.2.1. After verifying the repro still works a couple of minutes ago I upgraded to 4.3.2 and the Has No Surface! message is gone, even if you scroll to the other pages not containing the RiveAnimation. So I guess this was fixed and can be closed 😊

umberto-sonnino commented 1 year ago

Great to hear, going to close it then!