I got a fragment in which there's an animation of a count down clock. I want to start the animation as soon as the fragment loads without any intervention from the user.
What I do now is calling the following method in onCreateView:
private void startCountDownAnimation()
{
final int totalSeconds = secondsToStart + minutesToStart * 60;
mRingProgressBar.setTotalSeconds(totalSeconds);
HandlerThread handlerThread = new HandlerThread("countdown");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable()
{
#Override
public void run()
{
timer.scheduleAtFixedRate(new TimerTask()
{
//int secondsPassed = 0;
int secondsLeft = totalSeconds;
#Override
public void run()
{
if(secondsLeft == 0)
{
//fragment transaction
timer.cancel();
}
//final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f);
getActivity().runOnUiThread(new Runnable()
{
#Override
public void run()
{
mRingProgressBar.setSeconds(secondsLeft);
secondsLeft--;
//secondsPassed++;
}
});
}
}, 0, 1000);
}
});
}
This seems to work including when the app goes to the background.
I just want to know if what I'm doing is the correct way to handle the animation:
1) Is onCreate the correct place to call this method?
2) Can I have some issues of the app going to the background or if the screen blackens after a while?
3)Anything else I should change?
You should not use a Timer inside an Handler as the Timer is already asynchronous. The Timer is known to generate memory leaks so I'd suggest to use a CountDownTimer instead.
You should probably create the timer in onCreate and start it in onResume and stop it in onPause. Then you update the view in the onTick but you probably need to check if the view is available or not (view != null)
UPDATE : The code is working only that I dint init the textview, but this question is answered so I cant remove it either. So I will leave this question as it is for anyone trying to implement a Timertask with handler that makes use of Looper.getMainLooper that directly attaches it to the UI THREAD.
OLD QUERY :Hello guys I am trying to implement a timer that runs a task which has a handler.
I am using it to update the UI every second.
This is what I am implementing:
private void setRepeatingAsyncTask() {
handler = new Handler(Looper.getMainLooper());
timer = new Timer();
TimerTask task = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
public void run() {
try {
i++;
tview.setText(String.valueOf(i));
} catch (Exception e) {
// error, do something
}
}
});
}
};
timer.schedule(task, 0, 1000); // interval of one minute
}
when I make setRepeatingAsyncTask() on create or somewhere else like button clicklistner, etc either the timer or the handler is not starting.
Please help new to android!
I used Handler to process the task every 1 sec, Using just Handler:
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//some task
handler.postDelayed(this, 1000); //looping is every 1 secs
}
}, 0); //initial delay of 0
I am updating a counter in thread and its working fine.
But when the phone is in sleep and activity runs after aquiring wakelock, the thread not updates the UI using counter.
Here is my function where I am updating the view value.
private void updateTimeInBackground() {
new Thread(new Runnable() {
#Override
public void run() {
startAlarm();
int counter = MINUTE;
// in this function Im using the runOnUiThread(...) to update the view and also used TextView.post(...)
updateTextViewValue(counter);
if (isDismissed)
return;
updateOverlayForAlert();
counter = 0;
int minutes = 1;
vibrator.vibrate(1000);
// in this function Im using the runOnUiThread(...) to update the view and also used TextView.post(...)
updateTextViewValue(counter, minutes);
}
}).start();
Any suggestions? or hint?
Use TimerTask which will continue to run in the background.
Hope this helps.
Use Handler and Runnable instead of Thread
final Handler handler=new Handler();
runnable=new Runnable() {
#Override
public void run() {
handler.postDelayed(runnable, 5000);
// your code
}
};
runnable.run();
My app works with a few pictures. I want to take a new one every few seconds and add it to the pictures I work with. So I wrote this code, using an own Thread for the waiting time, so the ui won't freeze.
Handler handler = new Handler();
int time = 500;
for (int cnt = 10000; cnt > 0; cnt -= time) {
// Execute the code in run after time [ms] passed
handler.postDelayed(new Runnable() {
public void run() {
mainTask();
}
}, time);
}
Why does my ui freeze until the for loop ends? Usually the shown pictures should be updated in the mainTask()
Thanks for your help!
[EDIT]
It is working now, I created a class that implements Runnable and let it call itself:
Handler handler = new Handler();
class DelayedTask implements Runnable {
int cnt, time;
Handler handler;
DelayedTask(int c, int t, Handler h) {cnt=c; time=t; handler=h;}
public void run() {
mainTask();
if (cnt > 0) {
cnt -= time;
handler.postDelayed(new DelayedTask(cnt, time, handler), time);
}
}
}
handler.postDelayed(new DelayedTask(cnt,time,handler), time);
You're scheduling 10000/500 Runnables in a very short time, all firing after 500ms, at the same time. This is probably not what you want.
Instead, you want to schedule the next Runnable when the current Runnable fires:
handler.postDelayed(new Runnable() {
#Override
public void run() {
mainTask();
if(someCondition) {
handler.postDelayed(this, 500);
}
}
}, 500);
Now, mainTask will fire every ~500ms.
I am not too sure, but I think the handler goes like this:
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mainTask();
handler.postDelayed(this, interval);
}
}, interval);
I developed an application to display some text at defined intervals in the Android emulator screen. I am using the Handler class. Here is a snippet from my code:
handler = new Handler();
Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
}
};
handler.postDelayed(r, 1000);
When I run this application the text is displayed only once. Why?
The simple fix to your example is :
handler = new Handler();
final Runnable r = new Runnable() {
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(r, 1000);
Or we can use normal thread for example (with original Runner) :
Thread thread = new Thread() {
#Override
public void run() {
try {
while(true) {
sleep(1000);
handler.post(this);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
thread.start();
You may consider your runnable object just as a command that can be sent to the message queue for execution, and handler as just a helper object used to send that command.
More details are here http://developer.android.com/reference/android/os/Handler.html
new Handler().postDelayed(new Runnable() {
public void run() {
// do something...
}
}, 100);
I think can improve first solution of Alex2k8 for update correct each second
1.Original code:
public void run() {
tv.append("Hello World");
handler.postDelayed(this, 1000);
}
2.Analysis
In above cost, assume tv.append("Hello Word") cost T milliseconds, after display 500 times delayed time is 500*T milliseconds
It will increase delayed when run long time
3. Solution
To avoid that Just change order of postDelayed(), to avoid delayed:
public void run() {
handler.postDelayed(this, 1000);
tv.append("Hello World");
}
For repeating task you can use
new Timer().scheduleAtFixedRate(task, runAfterADelayForFirstTime, repeaingTimeInterval);
call it like
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
}
},500,1000);
The above code will run first time after half second(500) and repeat itself after each second(1000)
Where
task being the method to be executed
after the time to initial execution
(interval the time for repeating the execution)
Secondly
And you can also use CountDownTimer if you want to execute a Task number of times.
new CountDownTimer(40000, 1000) { //40000 milli seconds is total time, 1000 milli seconds is time interval
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
}
}.start();
//Above codes run 40 times after each second
And you can also do it with runnable. create a runnable method like
Runnable runnable = new Runnable()
{
#Override
public void run()
{
}
};
And call it in both these ways
new Handler().postDelayed(runnable, 500 );//where 500 is delayMillis // to work on mainThread
OR
new Thread(runnable).start();//to work in Background
I believe for this typical case, i.e. to run something with a fixed interval, Timer is more appropriate. Here is a simple example:
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
// If you want to modify a view in your Activity
MyActivity.this.runOnUiThread(new Runnable()
public void run(){
tv.append("Hello World");
});
}
}, 1000, 1000); // initial delay 1 second, interval 1 second
Using Timer has few advantages:
Initial delay and the interval can be easily specified in the schedule function arguments
The timer can be stopped by simply calling myTimer.cancel()
If you want to have only one thread running, remember to call myTimer.cancel() before scheduling a new one (if myTimer is not null)
Handler handler=new Handler();
Runnable r = new Runnable(){
public void run() {
tv.append("Hello World");
handler.postDelayed(r, 1000);
}
};
handler.post(r);
Kotlin
private lateinit var runnable: Runnable
override fun onCreate(savedInstanceState: Bundle?) {
val handler = Handler()
runnable = Runnable {
// do your work
handler.postDelayed(runnable, 2000)
}
handler.postDelayed(runnable, 2000)
}
Java
Runnable runnable;
Handler handler;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
// do your work
handler.postDelayed(this, 1000);
}
};
handler.postDelayed(runnable, 1000);
}
If I understand correctly the documentation of Handler.post() method:
Causes the Runnable r to be added to the message queue. The runnable will be run on the thread to which this handler is attached.
So examples provided by #alex2k8, even though are working correctly, are not the same.
In case, where Handler.post() is used, no new threads are created. You just post Runnable to the thread with Handler to be executed by EDT.
After that, EDT only executes Runnable.run(), nothing else.
Remember:
Runnable != Thread.
Kotlin with Coroutines
In Kotlin, using coroutines you can do the following:
CoroutineScope(Dispatchers.Main).launch { // Main, because UI is changed
ticker(delayMillis = 1000, initialDelayMillis = 1000).consumeEach {
tv.append("Hello World")
}
}
Try it out here!
An interesting example is you can continuously see a counter/stop-watch running in separate thread. Also showing GPS-Location. While main activity User Interface Thread is already there.
Excerpt:
try {
cnt++; scnt++;
now=System.currentTimeMillis();
r=rand.nextInt(6); r++;
loc=lm.getLastKnownLocation(best);
if(loc!=null) {
lat=loc.getLatitude();
lng=loc.getLongitude();
}
Thread.sleep(100);
handler.sendMessage(handler.obtainMessage());
} catch (InterruptedException e) {
Toast.makeText(this, "Error="+e.toString(), Toast.LENGTH_LONG).show();
}
To look at code see here:
Thread example displaying GPS Location and Current Time runnable alongside main-activity's User Interface Thread
now in Kotlin you can run threads this way:
class SimpleRunnable: Runnable {
public override fun run() {
println("${Thread.currentThread()} has run.")
}
}
fun main(args: Array<String>) {
val thread = SimpleThread()
thread.start() // Will output: Thread[Thread-0,5,main] has run.
val runnable = SimpleRunnable()
val thread1 = Thread(runnable)
thread1.start() // Will output: Thread[Thread-1,5,main] has run
}