/* * Copyright (C) 2016 Brian Wernick * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.devbrackets.android.exomedia.util; import android.os.Handler; import android.os.HandlerThread; import android.support.annotation.Nullable; /** * A method repeater to easily perform update functions on a timed basis. * <b>NOTE:</b> the duration between repeats may not be exact. If you require an exact * amount of elapsed time use the {@link StopWatch} instead. */ public class Repeater { private static final String HANDLER_THREAD_NAME = "ExoMedia_Repeater_HandlerThread"; private static final int DEFAULT_REPEAT_DELAY = 33; // ~30 fps private volatile boolean repeaterRunning = false; private int repeatDelay = DEFAULT_REPEAT_DELAY; private Handler delayedHandler; private HandlerThread handlerThread; private boolean useHandlerThread = false; private RepeatListener listener; private PollRunnable pollRunnable = new PollRunnable(); public Repeater() { this(true); } /** * @param processOnStartingThread True if the repeating process should be handled on the same thread that created the Repeater */ public Repeater(boolean processOnStartingThread) { if (processOnStartingThread) { delayedHandler = new Handler(); return; } useHandlerThread = true; } /** * @param handler The Handler to use for the repeating process */ public Repeater(Handler handler) { delayedHandler = handler; } /** * Sets the amount of time between method invocation. * * @param milliSeconds The time between method calls [default: {@value #DEFAULT_REPEAT_DELAY}] */ public void setRepeaterDelay(int milliSeconds) { repeatDelay = milliSeconds; } /** * Retrieves the amount of time between method invocation. * * @return The millisecond time between method calls */ public int getRepeaterDelay() { return repeatDelay; } /** * Starts the repeater */ public void start() { if (!repeaterRunning) { repeaterRunning = true; if (useHandlerThread) { handlerThread = new HandlerThread(HANDLER_THREAD_NAME); handlerThread.start(); delayedHandler = new Handler(handlerThread.getLooper()); } pollRunnable.performPoll(); } } /** * Stops the repeater */ public void stop() { if (handlerThread != null) { handlerThread.quit(); } repeaterRunning = false; } /** * Determines if the Repeater is currently running * * @return True if the repeater is currently running */ public boolean isRunning() { return repeaterRunning; } /** * Sets the listener to be notified for each repeat * * @param listener The listener or null */ public void setRepeatListener(@Nullable RepeatListener listener) { this.listener = listener; } public interface RepeatListener { void onRepeat(); } private class PollRunnable implements Runnable { @Override public void run() { if (listener != null) { listener.onRepeat(); } if (repeaterRunning) { performPoll(); } } public void performPoll() { delayedHandler.postDelayed(pollRunnable, repeatDelay); } } }