Class Choreographer

java.lang.Object
icyllis.modernui.core.Choreographer

@Internal public final class Choreographer extends Object
Coordinates the timing of animations, input and drawing.

The choreographer receives timing pulses (such as vertical synchronization) from the render thread then schedules work to occur as part of rendering the next display frame.

Applications typically interact with the choreographer indirectly using higher level abstractions in the animation framework or the view hierarchy. Here are some examples of things you can do using the higher-level APIs.

However, there are a few cases where you might want to use the functions of the choreographer directly in your application. Here are some examples.

Each Looper thread has its own choreographer. Other threads can post callbacks to run on the choreographer but they will run on the Looper to which the choreographer belongs.

  • Field Details

    • CALLBACK_INPUT

      @Internal public static final int CALLBACK_INPUT
      Callback type: Input callback. Runs first.
      See Also:
    • CALLBACK_ANIMATION

      @Internal public static final int CALLBACK_ANIMATION
      Callback type: Animation callback. Runs before CALLBACK_TRAVERSAL.
      See Also:
    • CALLBACK_TRAVERSAL

      @Internal public static final int CALLBACK_TRAVERSAL
      Callback type: Traversal callback. Handles layout and draw. Runs after all other asynchronous messages have been handled.
      See Also:
    • CALLBACK_COMMIT

      @Internal public static final int CALLBACK_COMMIT
      Callback type: Commit callback. Handles post-draw operations for the frame. Runs after traversal completes. The frame time reported during this callback may be updated to reflect delays that occurred while traversals were in progress in case heavy layout operations caused some frames to be skipped. The frame time reported during this callback provides a better estimate of the start time of the frame in which animations (and other updates to the view hierarchy state) actually took effect.
      See Also:
  • Method Details

    • getInstance

      @NonNull public static Choreographer getInstance()
      Gets the choreographer for the calling thread. Must be called from a thread that already has a Looper associated with it. Must NOT be called from render thread.
      Returns:
      The choreographer for this thread.
      Throws:
      IllegalStateException - if the thread does not have a looper
    • getFrameDelay

      @Internal public static long getFrameDelay()
      The amount of time, in milliseconds, between each frame of the animation.

      This is a requested time that the animation will attempt to honor, but the actual delay between frames may be different, depending on system load and capabilities. This is a static function because the same delay will be applied to all animations, since they are all run off of a single timing loop.

      Returns:
      the requested time between frames, in milliseconds
    • setFrameDelay

      @Internal public static void setFrameDelay(long frameDelay)
      The amount of time, in milliseconds, between each frame of the animation.

      This is a requested time that the animation will attempt to honor, but the actual delay between frames may be different, depending on system load and capabilities. This is a static function because the same delay will be applied to all animations, since they are all run off of a single timing loop.

      Parameters:
      frameDelay - the requested time between frames, in milliseconds
    • subtractFrameDelay

      @Internal public static long subtractFrameDelay(long delayMillis)
      Subtracts typical frame delay time from a delay interval in milliseconds.

      This method can be used to compensate for animation delay times that have baked in assumptions about the frame delay. For example, it's quite common for code to assume a 60Hz frame time and bake in a 16ms delay. When we call postCallbackDelayed(int, java.lang.Runnable, java.lang.Object, long) on animation we want to know how long to wait before posting the animation callback but let the animation timer take care of the remaining frame delay time.

      This method is somewhat conservative about how much of the frame delay it subtracts. It uses the same value returned by getFrameDelay() which by default is 10ms even though many parts of the system assume 16ms. Consequently, we might still wait 6ms before posting an animation callback that we want to run on the next frame, but this is much better than waiting a whole 16ms and likely missing the deadline.

      Parameters:
      delayMillis - The original delay time including an assumed frame delay.
      Returns:
      The adjusted delay time with the assumed frame delay subtracted out.
    • postCallback

      @Internal public void postCallback(int callbackType, @NonNull Runnable action, @Nullable Object token)
      Posts a callback to run on the next frame.

      The callback runs once then is automatically removed.

      Parameters:
      callbackType - The callback type.
      action - The callback action to run during the next frame.
      token - The callback token, or null if none.
      See Also:
    • postCallbackDelayed

      @Internal public void postCallbackDelayed(int callbackType, @NonNull Runnable action, @Nullable Object token, long delayMillis)
      Posts a callback to run on the next frame after the specified delay.

      The callback runs once then is automatically removed.

      Parameters:
      callbackType - The callback type.
      action - The callback action to run during the next frame after the specified delay.
      token - The callback token, or null if none.
      delayMillis - The delay time in milliseconds.
      See Also:
    • removeCallbacks

      @Internal public void removeCallbacks(int callbackType, @Nullable Runnable action, @Nullable Object token)
      Removes callbacks that have the specified action and token.
      Parameters:
      callbackType - The callback type.
      action - The action property of the callbacks to remove, or null to remove callbacks with any action.
      token - The token property of the callbacks to remove, or null to remove callbacks with any token.
      See Also:
    • postFrameCallback

      public void postFrameCallback(@NonNull Choreographer.FrameCallback callback)
      Posts a frame callback to run on the next frame.

      The callback runs once then is automatically removed.

      Parameters:
      callback - The frame callback to run during the next frame.
      See Also:
    • postFrameCallbackDelayed

      public void postFrameCallbackDelayed(@NonNull Choreographer.FrameCallback callback, long delayMillis)
      Posts a frame callback to run on the next frame after the specified delay.

      The callback runs once then is automatically removed.

      Parameters:
      callback - The frame callback to run during the next frame.
      delayMillis - The delay time in milliseconds.
      See Also:
    • removeFrameCallback

      public void removeFrameCallback(@NonNull Choreographer.FrameCallback callback)
      Removes a previously posted frame callback.
      Parameters:
      callback - The frame callback to remove.
      See Also:
    • getFrameTime

      @Internal public long getFrameTime()
      Gets the time when the current frame started.

      This method provides the time in milliseconds when the frame started being rendered. The frame time provides a stable time base for synchronizing animations and drawing. It should be used instead of Core.timeMillis() or Core.timeNanos() for animations and drawing in the UI. Using the frame time helps to reduce inter-frame jitter because the frame time is fixed at the time the frame was scheduled to start, regardless of when the animations or drawing callback actually runs. All callbacks that run as part of rendering a frame will observe the same frame time so using the frame time also helps to synchronize effects that are performed by different callbacks.

      Please note that the framework already takes care to process animations and drawing using the frame time as a stable time base. Most applications should not need to use the frame time information directly.

      This method should only be called from within a callback.

      Returns:
      The frame start time, in the Core.timeMillis() time base.
      Throws:
      IllegalStateException - if no frame is in progress.
    • getFrameTimeNanos

      @Internal public long getFrameTimeNanos()
      Same as getFrameTime() but with nanosecond precision.
      Returns:
      The frame start time, in the Core.timeNanos() time base.
      Throws:
      IllegalStateException - if no frame is in progress.
    • getLastFrameTimeNanos

      @Internal public long getLastFrameTimeNanos()
      Like getFrameTimeNanos(), but always returns the last frame time, not matter whether callbacks are currently running.
      Returns:
      The frame start time of the last frame, in the Core.timeNanos() time base.