我知道它很旧,但它是你永远需要的东西。我编写了一个名为 TimedTaskExecutor 的类,因为我需要每隔 x 毫秒运行一个特定命令,持续时间未知。我的首要任务之一是使 x 尽可能准确。我尝试使用 AsyncTask、Handlers 和 CountdownTimer,但都给了我不好的结果。这是课程:
package com.example.myapp;
import java.util.concurrent.TimeUnit;
/*
* MUST RUN IN BACKGROUND THREAD
*/
public class TimedTaskExecutor {
// ------------------------------ FIELDS ------------------------------
/**
*
*/
private double intervalInMilliseconds;
/**
*
*/
private IVoidEmptyCallback callback;
/**
*
*/
private long sleepInterval;
// --------------------------- CONSTRUCTORS ---------------------------
/**
* @param intervalInMilliseconds
* @param callback
*/
public TimedTaskExecutor(double intervalInMilliseconds, IVoidEmptyCallback callback, long sleepInterval) {
this.intervalInMilliseconds = intervalInMilliseconds;
this.callback = callback;
this.sleepInterval = sleepInterval;
}
// --------------------- GETTER / SETTER METHODS ---------------------
/**
* @return
*/
private IVoidEmptyCallback getCallback() {
return callback;
}
/**
* @return
*/
private double getIntervalInMilliseconds() {
return intervalInMilliseconds;
}
/**
* @return
*/
private long getSleepInterval() {
return sleepInterval;
}
// -------------------------- OTHER METHODS --------------------------
/**
*
*/
public void run(ICallback<Boolean> isRunningChecker) {
long nanosInterval = (long) (getIntervalInMilliseconds() * 1000000);
Long previousNanos = null;
while (isRunningChecker.callback()) {
long nanos = TimeUnit.NANOSECONDS.toNanos(System.nanoTime());
if (previousNanos == null || (double) (nanos - previousNanos) >= nanosInterval) {
getCallback().callback();
if (previousNanos != null) {
// Removing the difference
previousNanos = nanos - (nanos - previousNanos - nanosInterval);
} else {
previousNanos = nanos;
}
}
if (getSleepInterval() > 0) {
try {
Thread.sleep(getSleepInterval());
} catch (InterruptedException ignore) {
}
}
}
}
// -------------------------- INNER CLASSES --------------------------
/**
*
*/
public interface IVoidEmptyCallback {
/**
*
*/
public void callback();
}
/**
* @param <T>
*/
public interface ICallback<T> {
/**
* @return
*/
public T callback();
}
}
以下是如何使用它的示例:
private boolean running;
Handler handler = new Handler();
handler.postDelayed(
new Runnable() {
/**
*
*/
@Override
public void run() {
running = false;
}
},
5000
);
HandlerThread handlerThread = new HandlerThread("For background");
handlerThread.start();
Handler background = new Handler(handlerThread.getLooper());
background.post(
new Runnable() {
/**
*
*/
@Override
public void run() {
new TimedTaskExecutor(
10, // Run tick every 10 milliseconds
// The callback for each tick
new TimedTaskExecutor.IVoidEmptyCallback() {
/**
*
*/
private int counter = 1;
/**
*
*/
@Override
public void callback() {
// You can use the handler to post runnables to the UI
Log.d("runTimedTask", String.valueOf(counter++));
}
},
// sleep interval in order to allow the CPU to rest
2
).run(
// A callback to check when to stop
new TimedTaskExecutor.ICallback<Boolean>() {
/**
*
* @return
*/
@Override
public Boolean callback() {
return running;
}
}
);
}
}
);
运行此代码将产生 500 次或多或少准确 x 的调用。(降低睡眠因子使其更准确)
- 编辑:似乎在带有 Lollipop 的 Nexus 5 中,您应该在睡眠因子中使用 0。