Equivalent to javax.swing.Timer in Android
Is there something that looks like the javax.swing.Timer
on Android. I know how to create own Threads, but is there something that is like the s开发者_如何学Pythonwing-timer?
You are probably looking for the class android.os.CountDownTimer
You can inherit the class like this:
class MyTimer extends CountDownTimer
{
public MyTimer(int secsInFuture) {
super(secsInFuture*1000, 1000); //interval/ticks each second.
}
@Override
public void onFinish() {
Log.d("mytag","timer finished!");
}
@Override
public void onTick(long millisUntilFinished) {
//fired on each interval
Log.d("mytag","tick; " + millisUntilFinished + " ms left");
}
}
The main point of javax.swing.Timer
is that it executes tasks on GUI thread (EDT - event dispatching thread). This makes it safe to manipulate Swing components.
In Android there is also EDT and you should only manipulate GUI elements on EDT. To delay your code and then run it on EDT use view.postDelayed(runnable)
.
There is also Java's TimerTask. Here's an example from my code where I'm playing audio samples:
import java.util.Timer;
import java.util.TimerTask;
// from constructor, shown here out of place
timer = new Timer();
// and in method, again, shown out of place:
INTERVAL_MILLISECONDS = (int)((double)(bufSize) / (double)(nativeSampleRate * 2) * 1000);
timer.scheduleAtFixedRate( new TimerTask() {
public void run() {
synchronized(this){
track.write(data, 0, bufSize);
track.play();
}
}
}, 0, INTERVAL_MILLISECONDS);
The following code correctly handles (1) calling task on GUI thread, (2) not flooding GUI thread when task takes longer than delay time, (3) garbage collection when timer is stopped:
import android.os.Handler;
import android.os.Looper;
import java.util.ArrayList;
class ActionEvent {
public ActionEvent(Object src) {
}
}
interface ActionListener {
public void actionPerformed(ActionEvent e);
}
class Timer {
public Timer(int delay, ActionListener al) {
addActionListener(al);
_delay = delay;
}
public void addActionListener(ActionListener al) {
_listeners.add(al);
}
private void fireActionPerformed() {
for (ActionListener al : _listeners.toArray(new ActionListener[0])) {
al.actionPerformed(new ActionEvent(this));
}
}
private void fireAfterDelay() {
if (!_bStarted)
return;
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
public void run() {
if (_bStarted) {
fireActionPerformed();
if (_bStarted)
fireAfterDelay();
}
}
}, _delay);
}
public void start() {
if (!_bStarted) {
_bStarted = true;
fireAfterDelay();
}
}
public void stop() {
_bStarted = false;
}
private final ArrayList<ActionListener> _listeners = new ArrayList<>();
private int _delay;
private boolean _bStarted;
}
I put in classes ActionEvent and ActionListener for more compatibility with Java Swing. For simplicity you could remove ActionEvent and replace ActionListener with Runnable.
精彩评论