clean up Throttle
This commit is contained in:
parent
910ee75798
commit
b1edd02c08
1 changed files with 46 additions and 77 deletions
|
@ -29,50 +29,31 @@ import timber.log.Timber;
|
||||||
* This class used to "throttle" a flow of events.
|
* This class used to "throttle" a flow of events.
|
||||||
*
|
*
|
||||||
* When {@link #onEvent()} is called, it calls the callback in a certain timeout later.
|
* When {@link #onEvent()} is called, it calls the callback in a certain timeout later.
|
||||||
* Initially {@link #mMinTimeout} is used as the timeout, but if it gets multiple {@link #onEvent}
|
* Initially {@link #minTimeout} is used as the timeout, but if it gets multiple {@link #onEvent}
|
||||||
* calls in a certain amount of time, it extends the timeout, until it reaches {@link #mMaxTimeout}.
|
* calls in a certain amount of time, it extends the timeout, until it reaches {@link #maxTimeout}.
|
||||||
*
|
*
|
||||||
* This class is primarily used to throttle content changed events.
|
* This class is primarily used to throttle content changed events.
|
||||||
*/
|
*/
|
||||||
public class Throttle {
|
public class Throttle {
|
||||||
public static final boolean DEBUG = false; // Don't submit with true
|
private static final int TIMEOUT_EXTEND_INTERVAL = 500;
|
||||||
|
|
||||||
public static final int DEFAULT_MIN_TIMEOUT = 150;
|
|
||||||
public static final int DEFAULT_MAX_TIMEOUT = 2500;
|
|
||||||
/* package */ static final int TIMEOUT_EXTEND_INTERVAL = 500;
|
|
||||||
|
|
||||||
private static Timer TIMER = new Timer();
|
private static Timer TIMER = new Timer();
|
||||||
|
|
||||||
private final Clock mClock;
|
private final Clock clock;
|
||||||
private final Timer mTimer;
|
private final Timer timer;
|
||||||
|
|
||||||
/** Name of the instance. Only for logging. */
|
private final String name;
|
||||||
private final String mName;
|
private final Handler handler;
|
||||||
|
private final Runnable callback;
|
||||||
|
|
||||||
/** Handler for UI thread. */
|
private final int minTimeout;
|
||||||
private final Handler mHandler;
|
private final int maxTimeout;
|
||||||
|
private int currentTimeout;
|
||||||
/** Callback to be called */
|
|
||||||
private final Runnable mCallback;
|
|
||||||
|
|
||||||
/** Minimum (default) timeout, in milliseconds. */
|
|
||||||
private final int mMinTimeout;
|
|
||||||
|
|
||||||
/** Max timeout, in milliseconds. */
|
|
||||||
private final int mMaxTimeout;
|
|
||||||
|
|
||||||
/** Current timeout, in milliseconds. */
|
|
||||||
private int mTimeout;
|
|
||||||
|
|
||||||
/** When {@link #onEvent()} was last called. */
|
/** When {@link #onEvent()} was last called. */
|
||||||
private long mLastEventTime;
|
private long lastEventTime;
|
||||||
|
|
||||||
private MyTimerTask mRunningTimerTask;
|
private MyTimerTask runningTimerTask;
|
||||||
|
|
||||||
/** Constructor with default timeout */
|
|
||||||
public Throttle(String name, Runnable callback, Handler handler) {
|
|
||||||
this(name, callback, handler, DEFAULT_MIN_TIMEOUT, DEFAULT_MAX_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Constructor that takes custom timeout */
|
/** Constructor that takes custom timeout */
|
||||||
public Throttle(String name, Runnable callback, Handler handler,int minTimeout,
|
public Throttle(String name, Runnable callback, Handler handler,int minTimeout,
|
||||||
|
@ -81,64 +62,60 @@ public class Throttle {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor for tests */
|
/** Constructor for tests */
|
||||||
/* package */ Throttle(String name, Runnable callback, Handler handler,int minTimeout,
|
private Throttle(String name, Runnable callback, Handler handler, int minTimeout,
|
||||||
int maxTimeout, Clock clock, Timer timer) {
|
int maxTimeout, Clock clock, Timer timer) {
|
||||||
if (maxTimeout < minTimeout) {
|
if (maxTimeout < minTimeout) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
mName = name;
|
this.name = name;
|
||||||
mCallback = callback;
|
this.callback = callback;
|
||||||
mClock = clock;
|
this.clock = clock;
|
||||||
mTimer = timer;
|
this.timer = timer;
|
||||||
mHandler = handler;
|
this.handler = handler;
|
||||||
mMinTimeout = minTimeout;
|
this.minTimeout = minTimeout;
|
||||||
mMaxTimeout = maxTimeout;
|
this.maxTimeout = maxTimeout;
|
||||||
mTimeout = mMinTimeout;
|
currentTimeout = this.minTimeout;
|
||||||
}
|
|
||||||
|
|
||||||
private void debugLog(String message) {
|
|
||||||
Timber.d("Throttle: [%s] %s", mName, message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isCallbackScheduled() {
|
private boolean isCallbackScheduled() {
|
||||||
return mRunningTimerTask != null;
|
return runningTimerTask != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelScheduledCallback() {
|
public void cancelScheduledCallback() {
|
||||||
if (mRunningTimerTask != null) {
|
if (runningTimerTask != null) {
|
||||||
if (DEBUG) debugLog("Canceling scheduled callback");
|
Timber.d("Throttle: [%s] %s", name, "Canceling scheduled callback");
|
||||||
mRunningTimerTask.cancel();
|
runningTimerTask.cancel();
|
||||||
mRunningTimerTask = null;
|
runningTimerTask = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void updateTimeout() {
|
private void updateTimeout() {
|
||||||
final long now = mClock.getTime();
|
final long now = clock.getTime();
|
||||||
if ((now - mLastEventTime) <= TIMEOUT_EXTEND_INTERVAL) {
|
if ((now - lastEventTime) <= TIMEOUT_EXTEND_INTERVAL) {
|
||||||
mTimeout *= 2;
|
currentTimeout *= 2;
|
||||||
if (mTimeout >= mMaxTimeout) {
|
if (currentTimeout >= maxTimeout) {
|
||||||
mTimeout = mMaxTimeout;
|
currentTimeout = maxTimeout;
|
||||||
}
|
}
|
||||||
if (DEBUG) debugLog("Timeout extended " + mTimeout);
|
Timber.d("Throttle: [%s] %s", name, "Timeout extended " + currentTimeout);
|
||||||
} else {
|
} else {
|
||||||
mTimeout = mMinTimeout;
|
currentTimeout = minTimeout;
|
||||||
if (DEBUG) debugLog("Timeout reset to " + mTimeout);
|
Timber.d("Throttle: [%s] %s", name, "Timeout reset to " + currentTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLastEventTime = now;
|
lastEventTime = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onEvent() {
|
public void onEvent() {
|
||||||
if (DEBUG) debugLog("onEvent");
|
Timber.d("Throttle: [%s] %s", name, "onEvent");
|
||||||
|
|
||||||
updateTimeout();
|
updateTimeout();
|
||||||
|
|
||||||
if (isCallbackScheduled()) {
|
if (isCallbackScheduled()) {
|
||||||
if (DEBUG) debugLog(" callback already scheduled");
|
Timber.d("Throttle: [%s] %s", name, " callback already scheduled");
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) debugLog(" scheduling callback");
|
Timber.d("Throttle: [%s] %s", name, " scheduling callback");
|
||||||
mRunningTimerTask = new MyTimerTask();
|
runningTimerTask = new MyTimerTask();
|
||||||
mTimer.schedule(mRunningTimerTask, mTimeout);
|
timer.schedule(runningTimerTask, currentTimeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +127,7 @@ public class Throttle {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mHandler.post(new HandlerRunnable());
|
handler.post(new HandlerRunnable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -162,20 +139,12 @@ public class Throttle {
|
||||||
private class HandlerRunnable implements Runnable {
|
private class HandlerRunnable implements Runnable {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mRunningTimerTask = null;
|
runningTimerTask = null;
|
||||||
if (!mCanceled) { // This check has to be done on the UI thread.
|
if (!mCanceled) { // This check has to be done on the UI thread.
|
||||||
if (DEBUG) debugLog("Kicking callback");
|
Timber.d("Throttle: [%s] %s", name, "Kicking callback");
|
||||||
mCallback.run();
|
callback.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ int getTimeoutForTest() {
|
|
||||||
return mTimeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ long getLastEventTimeForTest() {
|
|
||||||
return mLastEventTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue