/* * Copyright (c) 2013, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * */ package com.marshalchen.common.uimodule.rebound; import android.annotation.TargetApi; import android.os.Build; import android.os.Handler; import android.view.Choreographer; /** * Android version of the spring looper that uses the most appropriate frame callback mechanism * available. It uses Android's {@link android.view.Choreographer} when available, otherwise it uses a * {@link android.os.Handler}. */ public abstract class AndroidSpringLooperFactory { /** * Create an Android {@link SpringLooper} for the detected Android platform. * @return a SpringLooper */ public static SpringLooper createSpringLooper() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return ChoreographerAndroidSpringLooper.create(); } else { return LegacyAndroidSpringLooper.create(); } } /** * The base implementation of the Android spring looper, using a {@link android.os.Handler} for the * frame callbacks. */ private static class LegacyAndroidSpringLooper extends SpringLooper { private final Handler mHandler; private final Runnable mLooperRunnable; private boolean mStarted; /** * @return an Android spring looper using a new {@link android.os.Handler} instance */ public static SpringLooper create() { return new LegacyAndroidSpringLooper(new Handler()); } public LegacyAndroidSpringLooper(Handler handler) { mHandler = handler; mLooperRunnable = new Runnable() { @Override public void run() { if (!mStarted || mSpringSystem == null) { return; } mSpringSystem.loop(); mHandler.post(mLooperRunnable); } }; } @Override public void start() { mStarted = true; mHandler.removeCallbacks(mLooperRunnable); mHandler.post(mLooperRunnable); } @Override public void stop() { mStarted = false; mHandler.removeCallbacks(mLooperRunnable); } } /** * The Jelly Bean and up implementation of the spring looper that uses Android's * {@link android.view.Choreographer} instead of a {@link android.os.Handler} */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private static class ChoreographerAndroidSpringLooper extends SpringLooper { private final Choreographer mChoreographer; private final Choreographer.FrameCallback mFrameCallback; private boolean mStarted; /** * @return an Android spring choreographer using the system {@link android.view.Choreographer} */ public static ChoreographerAndroidSpringLooper create() { return new ChoreographerAndroidSpringLooper(Choreographer.getInstance()); } public ChoreographerAndroidSpringLooper(Choreographer choreographer) { mChoreographer = choreographer; mFrameCallback = new Choreographer.FrameCallback() { @Override public void doFrame(long frameTimeNanos) { if (!mStarted || mSpringSystem == null) { return; } mSpringSystem.loop(); mChoreographer.postFrameCallback(mFrameCallback); } }; } @Override public void start() { mStarted = true; mChoreographer.removeFrameCallback(mFrameCallback); mChoreographer.postFrameCallback(mFrameCallback); } @Override public void stop() { mStarted = false; mChoreographer.removeFrameCallback(mFrameCallback); } } }