Reusing timer in android - android

In my android app, I have the following relevant piece of code:
/*Code outside*/
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Timer t = new Timer();
t.scheduleAtFixedRate(
new TimerTask(){
public void run(){
stuffToBeDone();
}
},someVariableDelay,someVariablePeriod);
}
}
Everything was going fine until I noticed that stuffToBeDone() was running once for every time I pressed the button. As far as I understand, every time onClick() is called and the old Timer should not exist anymore, but somehow the TimerTask survives.
In the second button click, I no longer have a reference to the first Timer to cancel() it (because it should not exist anymore). And if I declare the Timer as a final variable in the Code outside so that I can do it, after canceling I cannot reuse it anymore. So how can I terminate that TimerTask but then still be able to use a Timer?

Android Timer is thread based from the Android Developers website:
http://developer.android.com/reference/java/util/Timer.html
When a timer is no longer needed, users should call cancel(), which releases the timer's thread and other resources. Timers not explicitly cancelled may hold resources indefinitely.
I would recommend instantiating the timer inside the onclicklistener only i.e. something similar to this:
/*Code outside*/
Timer t = null;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(t == null)
t = new Timer();
else
t.cancel();
t.scheduleAtFixedRate(
new TimerTask(){
public void run(){
stuffToBeDone();
}
},someVariableDelay,someVariablePeriod);
}
}

Related

Auto Redirect When User Is Taking Too Long Input In Activity Android

I have a scenario, which when a User Rating, or inputting on a data, then the current Activity will Time it to the setted time.
So, if the User isn't do Anything, or taking the Action to Long, then the current Activity will direct the User into the MainActivity.
In my case, i have a Rating app, which is located in a Public place. I thought that if People wants to Rate BUT not completing the Quiz phase, then i don't want to leave the last Quiz to meet the new People who wants to Rate.
I've tried using these code:
int timeout = 4000;
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
Intent homepage = new Intent(Quiz2.this, MainActivity.class);
startActivity(homepage);
finish();
}
}, timeout);
And these one:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(Quiz2.this, MainActivity.class));
}
}, 4000);
It works, but it didn't work as expected, as it apply to ALL of the activities (I mean, after these code works in Current Activity, the Rest of the Activities is Applied and Timed too)
I don't want this. What i want is to Apply these Timer ONLY in Current Activity.
How this can be done?
Appreciate for any help, Regards.
I didn't fully understand what you actually wanna do,
but I'm guessing using CountDownTimer and then starting the other activity when the timer finished should do the trick.
new CountDownTimer(4000, 1000) {
public void onTick(long millisUntilFinished) {
// You could show the user the time left using `millisUntilFinished`
}
public void onFinish() {
// Do something when the timer is finished (start your activity & finish)
}
}.start();

Small android animation delay issue

I just want to call a function after every 3secs on click of a button
What is going wrong here-
galleryBtn.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
final Handler handler = new Handler();
for(int i = 0;i<3;i++){
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Do something after 5s = 5000ms
viewAnimator.showNext();
}
}, 3000);
}
}
});
You don't actually say what goes wrong but I'll take a wild guess that nothing happens (i.e. no animations) and the reason for that is probably that your Handler is being GC'd long before it gets to handle anything. Try keeping moving 'handlers' scope from local variable to class member.
(Also note that, even when it works, all 3 of your functions will run at more or less the same time. If you want them to run 3 seconds apart you should change the '3000' to 'i*3000'.)

Updating UI on button click after a certain time

I have a TextView. I want to update its text (append a "1") after 1 second of a button click.
public class HaikuDisplay extends Activity {
Method m;
Timer t;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
t = new Timer();
m = HaikuDisplay.class.getMethod("change");
}
//Event handler of the button
public void onRefresh(View view)
{
//To have the reference of this inside the TimerTask
final HaikuDisplay hd = this;
TimerTask task1 = new TimerTask(){
public void run(){
/*
* I tried to update the text here but since this is not the UI thread, it does not allow to do so.
*/
//Calls change() method
m.invoke(hd, (Object[])null);
}
};
t.schedule(task1, 1000);
}
public void change()
{
//Appends a "1" to the TextView
TextView t = (TextView)findViewById(R.id.textView1);
t.setText(t.getText() + "1");
}
//Event handler of another button which updates the text directly by appending "2".
//This works fine unless I click the first button.
public void onRefresh1(View view)
{
TextView t = (TextView)findViewById(R.id.textView1);
t.setText(t.getText() + "2");
}
}
Consider all Exceptions be handled.
On first click, m.invoke gives InvocationTargetException. But it calls the method change() on successive invokes without any Exceptions(verified by logging). But it does not update the text. Where am I wrong?
Also, I see in the debugger that it creates a new Thread every time I click the button. That is fine. But why isn't it removing the previous Threads though their execution has been completed?
Do something like this
public void onRefresh1(View v) {
// You can have this in a field not to find it every time
final EditText t = (EditText) findViewById(R.id.textView1);
t.postDelayed(new Runnable() {
#Override
public void run() {
t.append("1");
}
}, 1000);
}
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Update UI
}
}, 1000);
implement this on button click
UPDATE:
There are some other answers. dtmilano suggested another solution which is almost same to mine except he is calling the postDelayed method of View class and In my answer I used postDelayed method of handler class.
from the api reference of android the postDelayed method of Handler says
The runnable will be run on the thread to which this handler is
attached.
and the postDelayed method of View says
The runnable will be run on the user interface thread.
This is the only difference between these two solution. in my answer instead of creating new Handler every time you can use any other handler instance. Then the runnable will be run on that thread where that specific handler is declared. And if the postDelayed of EditText is used the the runnable method will be run on the user Interface Thread.
Now the performance issue, both has the same performance (If anybody can prove me wrong with reference I will be happy)
That's looking awful convoluted - have you considered using CountDownTimer instead?
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
// no-op
}
public void onFinish() {
change();
}
}.start();
This should call change (and hence change the text) on the UI thread, avoiding reflection and threading errors.
Hi Use the following code for that. Hope this will help you .
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
// your code here
}
},
1000
);
Have a look of this question also.
display data after every 10 seconds in Android
You can try with this also.
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
public void run() {
doStuff();
/*
* Now register it for running next time
*/
handler.postDelayed(this, 1000);
}
};
**EDIT 3**
Try with this once you are need to enable once (i mean if you put your code in yourmethod()== this will get automatically call 1 seconds once.
private Timer timer;
TimerTask refresher;
// Initialization code in onCreate or similar:
timer = new Timer();
refresher = new TimerTask() {
public void run() {
yourmethod();
};
};
// first event immediately, following after 1 seconds each
timer.scheduleAtFixedRate(refresher, 0,100);

How do I set up a Timer.scheduleAtFixedRate() that actually works?

I am using Eclipse for Android. I am trying to make a simple repeating Timer that has a short delay.
It will start after a TextView timerTV is clicked. This code is in the onCreate method:
timerTV = (TextView) findViewById(R.id.timerTV);
timerTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Timer gameTimer = new Timer();
TimerTask doThis;
int delay = 5000; // delay for 5 sec.
int period = 1000; // repeat every sec.
doThis = new TimerTask() {
public void run() {
Toast.makeText(getApplicationContext(), "timer is running", Toast.LENGTH_SHORT).show();
}
};
gameTimer.scheduleAtFixedRate(doThis, delay, period);
Everytime I try to run it, a "Class File Editor" pops up with the error:
"Source not found"
The JAR file C:\Program Files\Android\android-sdk\platforms\android-8\android.jar has no source attachment.
You can attach the source by clicking Attach Source below:
[Attach Source...]
When I click this, Eclipse asks me to select the location folder containing 'android.jar'
I tried to do this, but cannot navigate all the way to the folder it is located in anyway.
I presume the issue is in my code somewhere.
I have been searching for hours, even copied and pasted code many times.
Using an actual Timer (java.util.Timer) in conjunction with runOnUiThread() is one way to solve this issue, and below is an example of how to implement it.
public class myActivity extends Activity {
private Timer myTimer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 0, 1000);
}
private void TimerMethod()
{
//This method is called directly by the timer
//and runs in the same thread as the timer.
//We call the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
//Do something to the UI thread here
}
};
}
SOURCE: http://steve.odyfamily.com/?p=12
Try using Project -> Clean then right click your project and find Fix Project Properties. Check your Build Path. It could be any one of these things. Restart eclipse, make sure your Android Manifest is targeting the correct API, 8 I assume?

Android TimerTask crashes when called twice

I'm calling my TimerTask (m_timer) upon a button click:
m_timer.schedule(m_progressUpdater, 0, 500);
Which kicks off my run method:
#Override
public void run() {
//do some stuff
progressBar.setProgress(currentProgress);
if (progress >= 100) {
handler.post(new Runnable() {
#Override
public void run() {
CompleteTask();
}
});
}
}
I can call this once and it works perfectly. When I call it again, my app stops responding. I'm thinking that I need to cancel the task in my CompleteTask() method, but I've tried cancelling both the TimerTask and the Timer, and it still crashes. Anyone know what the problem might be?
Have you tried creating new TimerTask instance for the second call? And by the way, don't cancel the timer otherwise it will cancel all of its task. And what did the log say?
When you reschedule a Timer, it throws:
java.lang.IllegalStateException: TimerTask is scheduled already
It seems that you can only use a timer for once.
In order to reschedule a Timer, you need to simply create a new instance of it, each time. like the following:
// if you have already started a TimerTask,
// you must(?) terminate the timer before rescheduling it again.
if(m_timer != null)
m_timer.cancel();
m_timer = new Timer();
m_progressUpdater = new myTimerTask();
m_timer.schedule(m_progressUpdater, 0, 500);

Categories

Resources