I have created a simple interval running timer and it works. The only problem is when the screen orientation changes (which could happen when running) the handler to the UI thread is lost (I think) and terefore the UI doesn't get updated when the run is over.
Can you guys help me out?
Here's my code:
public class MainActivity extends Activity {
private Thread workerThread;
private Handler uiHandler;
private EditText input;
private Button start, stop;
private ImageView image;
@Override protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Getting references to views
input = (EditText) findViewById(R.id.input);
start = (Button) findViewById(R.id.start);
stop = (Button) findViewById(R.id.stop);
image = (ImageView) findViewById(R.id.flash);
//Other vars
uiHandler = new Handler();
final String tag = "MainActivity";
final Pattern regex = Pattern.compile("^" +
"\\d+ (" +
" (\\.\\d+) |" +
" (\\(" +
" \\d+((\\.\\d+)? (,\\d+((\\.\\d+)?))*" +
" \\))" +
"))?" +
"(,\\d+ (" +
" (\\.\\d+) |" +
" (\\(" +
" \\d+((\\.\\d+)? (,\\d+((\\.\\d+)?))*" +
" \\))" +
"))?)*" +
"$"
, Pattern.COMMENTS);
//Restore previous state
try {
setUIRunning(savedInstanceState.getBoolean("running"));
} catch (Exception e) {
//New instance, do nothing
}
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick (View v) {
final List<Double> schedule;
//Process the input
try {
schedule = processInput(regex, input.getText().toString());
//Bad input, show a toast and stop
} catch (RegexFailedException e) {
Toast.makeText(getApplicationContext(), e.msg, Toast.LENGTH_SHORT).show();
return;
}
Log.v(tag, "Current running list: " + schedule.toString());
workerThread = new Thread(new Runnable() {
@Override
public void run () {
//SetUiRunning, but as a Runnable
class setUiRunningRunnable implements Runnable {
boolean par;
setUiRunningRunnable (boolean par) {
this.par = par;
uiHandler.post(this);
}
@Override public void run () { setUIRunning(par); }
}
class Flash {
public void run () {
uiHandler.post(new Runnable() {
@Override
public void run () {
//Show red
image.setVisibility(View.VISIBLE);
//Beep
(new ToneGenerator(AudioManager.STREAM_NOTIFICATION, 100))
.startTone(ToneGenerator.TONE_CDMA_ABBR_ALERT, 500);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Log.d(tag, "Sleeping (in flash) interrupted");
return;
}
//Hide red
uiHandler.post(new Runnable() {
@Override
public void run () {
image.setVisibility(View.GONE);
}
});
}
}
final Flash flash = new Flash();
class Main {
public void run () {
for (double interval : schedule) {
Long sleep = Math.round(interval * 60 * 1000);
try {
Log.d(tag, "sleeping for " + sleep + " ms");
Thread.sleep(sleep);
} catch (InterruptedException e) {
Log.d(tag, "Sleeping interrupted");
return;
}
flash.run();
Log.d(tag, "run flash");
}
}
}
final Main main = new Main();
//Thread started, updating the UI to running
new setUiRunningRunnable(true);
Log.d(tag, "thread started");
main.run();
//Thread started, updating the UI to idle
new setUiRunningRunnable(false);
Log.d(tag, "thread stopped");
}
});
workerThread.start();
}
});
stop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick (View v) {
setUIRunning(false);
workerThread.interrupt();
}
});
}
Any general advice is appreciated as well :)