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

First use of awaitFrame() awaits extra draw frame when used with Main dispatcher #3432

Closed
pablobaxter opened this issue Sep 2, 2022 · 0 comments

Comments

@pablobaxter
Copy link
Contributor

When using awaitFrame() for the first time on the main dispatcher, there is a wasted draw frame with the current implementation. This is due to the extra dispatch() call that is made for updateChoreographerAndPostFrameCallback before frame callback is set. Since dispatch() on the HandlerContext posts a message at the end of the main Looper queue, it is very likely that a frame render event would have already occurred by the time Choreographer.postFrameCallback {} is called, at which case, awaitFrame() actually awaits until the second frame before returning.

The following code snippet demonstrates the issue (I do admit it is a bit exaggerated in this code snippet):

class MainActivity : AppCompatActivity() {

    private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        println(1)
        Choreographer.getInstance().postFrameCallback { first -> // This was the first callback set
            println(4)
            Choreographer.getInstance().postFrameCallback { second ->
                println(7)
            }
        }

        scope.launch {
            println(2)
            awaitFrame() // Expect this to be the second callback set
            println(5)
        }

        println(3)
        Choreographer.getInstance().postFrameCallback { first -> // This is the third callback set
            println(6)
            Choreographer.getInstance().postFrameCallback { second ->
                println(8)
            }
        }
    }
}

The output for this would be:

I/System.out: 1
I/System.out: 2
I/System.out: 3
I/System.out: 4
I/System.out: 6
I/System.out: 7
I/System.out: 8
I/System.out: 5

The code defines the expected order output, however the output shows that the awaitFrame() call is made last, and after the second frame callbacks have been made. I have a potential fix in #3431

@pablobaxter pablobaxter changed the title Extra draw frame rendered on for first use of awaitFrame() when used with Main dispatcher Extra draw frame rendered on first use of awaitFrame() when used with Main dispatcher Sep 2, 2022
@pablobaxter pablobaxter changed the title Extra draw frame rendered on first use of awaitFrame() when used with Main dispatcher First use of awaitFrame() awaits extra draw frame when used with Main dispatcher Sep 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants