How do I use Android's CountDownTimer? - android

How do I use the Android's CountDownTimer?
I basically want to have the following scenario:
boolean 3_s_passed = false;
// setup counter to change 3_s_passed=true when it finishes
counter.start();
while(true){
if(3_s_passed || user_is_Done) break;
// do some stuff which may set user_is_Done to true
}
So either 3 seconds passed or the user finishes and I'm out of the loop.
Will the while-loop code run before the counter finishes? Is my understanding of the CountDownTimer correct?
Thanks for your help

You could use a handler for this. Make a Runnable with the task to complete after 3 seconds or when the user does the task. Post it for 3 seconds and remove callbacks if the user does whatever. The code same below shows how to properly use the Handler but isn't looping to allow the user to make the action you'll have to figure that out on your own :)
Runnable action = new Runnable(){
public void run(){
//...
}
};
mHandler.postDelayed(action, 3000);
if(userDone){
mHandler.removeCallbacks(action);
mHandler.post(action);
}

Don't use this class it contains a race in cancel method.
https://code.google.com/p/android/issues/detail?id=58668
cancel don't work in case of race between onTick and cancel.
It's better to implement it from scratch without races.
In other case you will have a problem until official fix.

Related

Android: what are the pros and cons of using a CountDownTimer vs Thread.sleep()?

What I want to do:
I am wanting to use a worker-thread to regularly update a textfield in the UI Thread. Let's say, every 2 seconds for 30 seconds. I need the 30 second countdown to happen even if the app is not on the foreground. For now, I am evaluating the merits of two different approaches (both using worker-threads) in implementing this. I won't post the full code here to simplify things and also because I am not asking to find any problem in my code. Both solutions work fine.
Solution #1 - use Thread.sleep() inside a for loop
for (int i = 30; i > 0; i-=2) {
Message msg = mHandler.obtainMessage(MSG_ID, i, 0);
msg.sendToTarget();
try {
Thread.sleep(2000);
} catch(Throwable t) {
// catch error
}
}
Solution #2 - use CountDownTimer
Looper.prepare()
new CountDownTimer(30000, 2000) {
public void onTick(long millUntilFinish) {
int seconds = (int)(millUntilFinish);
Message msg = mHandler.obtainMessage(MSG_ID, seconds, 0);
msg.sendToTarget();
}
public void onFinish() {
// left blank for now
}
}.start();
Looper.loop();
My Question
While both work, I am wanting to know if there is a "better" or a "preferred" way to do it for whatever reason. I am thinking there may be areas particularly in battery life but also in performance, accuracy or code design where one solution is better than the other.
What I have done so far to answer this question
My own evaluation so far from reading this SO question and CountDownTimer's documentation are that since both are executed on the worker-thread, both have no ANR possibility. Both solutions will also gaurantee that one "update" will happen only after the previous update has finished. Unfortunately, this is all I have and hoping if anyone can help or guide me to an insightful and/or similar SO question I may have overlooked or was unsuccessful in finding.
I write this question a bit cautiously as I don't have a problematic code which requires debugging but I think this falls within SO's category of a "specific programming problem", which hasn't been answered, and not included in the list of off-topic answers.
1.Calling Thread.sleep pauses the thread execution for a while where as countdown timer actually uses callbacks to notify timer expiry events and is asynchronous in nature.
2.If the thread execution pauses, you will not be able to use that specific thread for any other operation until the sleep timeout hence it is not recommended to use Thread.sleep approach. Obviously there is a load on cpu if it has to resume the thread execution and pause it.Where as in the case of countdown timer the thread continue to be in execution/idle state and as when events occur it fires to the respective listeners.
call Thread.sleep() method is not good idea beacuse ii sleep the UI Thread and disadvantage of CountDownTimer is, It Will stop when ur screen is off hence instead of this two try Handler for that like this
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run()
{
if (dataReceived)
{
cancelHandler();
}
}
};
handler.postDelayed(runnable, 100);
}
public void cancelHandler()
{
handler.removeCallbacks(runnable);
}

How to set up a timer for an android game ?

I want to programm a game for Android.
Play principle: The user should have a short time to choose the correct answer.
My problem is the combination between the input (choosing the answer) and the time (countdown). I tried to run a thread, but the thread isn't stoppable. So the user gives the answer, the next activity will be shown and after a while (when the "timer" becomes 0) the activity will be shown again.
How could I implement this in a correct way?
Should I use Thread, Handler, CountDownTimer ?
You can keep a running timer using this on init:
Timer updateTimer = new Timer("update");
updateTimer.scheduleAtFixedRate(new TimerTask() {
public void run() {
updateGUI();
}
}, 0, 1000);
long startTime = System.currentTimeMillis();
Then in a Thread:
//Clock update
currentTime = System.currentTimeMillis() - startTime;
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
clock.setText(sdf.format(currentTime));
clock.invalidate();
You could stop the Thread with a boolean inside or outside as you please?
Okay, I don't know the specific libraries to use, and I haven't done any thread programming myself, but I would think of the program as a state machine. I hope it helps :/
Set up a boolean userHasAnswered = false.
Set up a specialized listener (e.g. touch listener for some button) for answers.
If the listener gets an appropriate response from the user, set userHasAnswered = true.
When question loads up, start the thread which counts down.
If user fails to give ans when the time reaches zero, just call loadNextQuestion().
In your thread, do periodic checks every few units of time to see if userHasAnswered == true, and if it is true, then call updateScore() and loadNextQuestion().
You may want to have a look at alarm manager

How can I keep UI elements responsive while my program is working?

The UI I am creating includes a button, which once pressed, is supposed to find and display values repetitively until the user presses the button again.
This is my button's initialization with the listener:
pollOn = false;
pollButton = (Button) findViewById( R.id.pollButton );
pollButton.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i( "POLL BUTTON", "onClick" );
if( !pollOn ) {
Log.i( "POLL BUTTON", "!pollOn" );
pollOn = true;
methodToReadAndDisplayData();
} else {
Log.i( "POLL BUTTON", "else pollOn" );
pollOn = false;
}
}
});
It is not shown here to make things easier to read, but the way I currently have it working is to call the methodToReadAndDisplayData() 5 times in a for loop and then stop.
So when I press the pollButton initially, the UI freezes and Log.i("POLL BUTTON", "onClick") is displayed at the top of LogCat. I then press the pollButton while it appears to be frozen, and after all of the work is done and the UI unfreezes, Log.i("POLL BUTTON", "onClick") is shown at the very end of my LogCat. The way I am interpretting this is that the button click is entered into a queue, and the onClick method is called after all 5 iterations of the for loop have been completed.
Another large part of this problem is that the work being done is mainly in a native library, and is called using the NDK. I am unsure if this has anything to do with the UI freezing, but it definitely increases the processing time needed.
If anything is unclear or confusing please let me know and I will try to clarify things.
Any information on this situation would be greatly appreciated.
Doing some stuff while keeping the UI responsive can achieved by many methods, two of them are very common. Async Task and threads.
AsyncTask:
It's a class which have a few methods which help you to do time consuming work while updating the UI at the same time. For Example: If you want to search a specific word in a big document, do the reading and searching stuff in doInBackground() (a method of AsyncTask class) and you can display a progress bar and notify the user with your progress with onProgressUpdate(). This gives your app more professional feel and at the same time helps you executing time consuming task in background.
Threads:
They are simple runnable threads. You can execute non UI stuff with these threads but you can't perform UI tasks in them (as UI is not thread safe). For dealing with UI in these threads, you will have to use Handlers, which is quite cumbersome for beginners to get a grip and understanding of them.
So depending on your needs and app you can choose the one best suits you.
Because you're running on the main thread the system UI freezes, you'd be better off running in a new thread which would leave your UI running as normal. Below is an example of how to run your method in a new thread.
new Thread(new Runnable() {
#Override
public void run() {
methodToReadAndDisplayData();
}
}).start();
Note that if your method interacts with the UI in any way, you need to do it via the following:
When you want to update your UI:
Handler threadHandler = new Handler();
threadHandler.post(updateRunnable);
Update your UI here:
Runnable updateRunnable = new Runnable() {
public void run() {
example.setText(newValue);
}
};
Try that and see if there's any improvement. I've not worked with the NDK, just the standard SDK so there may be difference I'm unaware of.
Do it on another thread. Use an AsyncTask to call methodToReadAndDisplayData.

Android terminating a thread created through runnable

Let's say in various points in my application, I create and fire off a new runnable like so:
new Thread(new Runnable() {
public void run() {
while(true) {
//do lots of stuff
//draw lots of stuff on screen, have a good ol time
//total loop processing time abt 1250-1500ms
//check for conditions to stop the loop, break;
} } }
Now, is there any way to terminate that thread midway through execution other than break; inside my while loop? I'd like to be able to kill it specifically and immediately from the parent thread, like, as in the event that the user just requested to load a different map. It feels clunky to insert an if (stopFlag) break; (set in parent thread) after every 5 or so lines of code.
I peeked at Runnable's and Thread's methods and I just can't see it. Someone know an awesome trick?
You may use AsyncTask and call cancel to cancel the thread.
Instead of while (true) you may check for a condition or a flag that would be changed properly when the Thread/Runnable should be stopped. This seems to be the suggested strategy since Thread.stop() has been deprecated.
You could use AsyncTask as suggested, which probably works best in this case. I believe you can also use the interrupt() method, which is preferred if good if you're not in Android, but still suffers from having to explicitly check if it is interrupted:
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
// do some stuff
if (isInterrupted()) {
break;
}
}
});
t.start();
// Whoa! Need to stop that work!
t.interrupt();

Android 2.2: How can you write a helper method to have your app 'sleep' for N milliseconds?

I need to write a helper method which I can use in various places in the app to essentially make it 'sleep' for N milliseconds.It looks like Handler.postAtTime may be one way to do it, but I'd like any code snippets if available.
You did not say why you need your app to "sleep".
Assuming you need to run a task after some time:
Handler h = new Handler();
h.postDelayed(new Runnable() {
public void run() {
// do something here
}
}, 1000); // 1000 ms delay
If you don't mind blocking the thread, an alternative to Thread.sleep() is SystemClock.sleep().
Benefit is that it's a one-liner, as it ignores the
InterruptedException so you don't need to handle it.
More info on http://developer.android.com/reference/android/os/SystemClock.html.
As already stated, you should avoid calling this on the main UI thread as it will cause your app to become unresponsive and potentially show the dreaded dialog we all hate to see (please wait or force close.)
Are you looking for something like this?
try {
//Put the thread to sleep for the desired amount of time (milliseconds)
Thread.currentThread().sleep(1000);
}
catch(InterruptedException ie){
}
This will put the thread you are calling it from to sleep for the amount of time you specify.

Categories

Resources