I have this code in MainActivity:
boolean running = true;
#Override
public void onClick(View v) {
Button button = (Button)findViewById(R.id.start);
new Thread(new Runnable() {
public void run() {
int secs = 1;
while(running){
Utils.delay(secs, new Utils.DelayCallback() {
int seconds = 0;
TextView licznik = (TextView)findViewById(R.id.licznik);
#Override
public void afterDelay() {
seconds = seconds + 1;
licznik.setText(Integer.toString(seconds));
}
});
}
}
}).start();
}
and its Utils class:
import android.os.Handler;
public class Utils {
// Delay mechanism
public interface DelayCallback{
void afterDelay();
}
public static void delay(int secs, final DelayCallback delayCallback){
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
delayCallback.afterDelay();
}
}, secs * 1000); // afterDelay will be executed after (secs*1000) milliseconds.
}
}
I found this method on StackOverflow, but it crashes my app after I click the button
What's wrong? Please help, if I should do another method for delay, tell me which
error:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
You are creating a Handler on a background Thread that hasn't called Looper.prepare(), and also touching a UI component off of the main thread.
Try:
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
delayCallback.afterDelay();
}
}, secs * 1000);
and see if that fixes the problem. Either way, though, you'll probably run into issues, since the while(running) call is going to trigger a lot without a sleep...
I cannot make a simple program to update the UI.
What I am looking to do is create a timer in a for loop that is initiated on a button click
public void buttonClick(View v);
for(int i=0;i<100;i++){
textView.setText(i+"");
try{
thread.sleep(1000);
catch{(yadayadayada)
}
}
I'm trying to make a counter in a for loop to update a text view with a one millisecond delay.
My second try and still no good
package com.example.dbq;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
Handler mHandler = new Handler();
TextView tv1;
Button b1;
int n=1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1=(TextView)findViewById(R.id.textView1);
b1 =(Button)findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i=0;i<100;i++){
Runnable r=new Runnable() {
#Override
public void run() {
tv1.setText(n +" runs");
}
};
mHandler.post(r);
mHandler.postDelayed(r, 1000);
n++;
}
}
}); //end onclick
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Do not use thread.sleep - you do not need to sleep your thread - you need update your UI at certain intervals and this is something different. Simply use Handler, then create Runnable that either updates your UI or calls the methods to do so and finally post your Runnable using Handler.postDelayed(). To keep the timer work, your Runnable have to post itself again, but that's shall be pretty obvious. And remember to remove your queued runnable when you are going to leave your fragment/activity
Use a timer scheduled at a fixed rate. The below updated text view with a count which is incremented every second.
Remember to update text view on the UI thread and cancel the timer whenever required.
_tv = (TextView) findViewById( R.id.textView1 );
On Button click initiate a timer. Start button to start a timer.
_t = new Timer();
_t.scheduleAtFixedRate( new TimerTask() {
#Override
public void run() {
_count++;
runOnUiThread(new Runnable() //run on ui thread
{
public void run()
{
_tv.setText(""+_count);
}
});
}
}, 1000, 1000 );
Have another button stop to cancel the timer
_t.cancel();
You can also use a handler as suggested by WebnetMobile
I have a variable in my code say it is "status".
I want to display some text in the application depending on this variable value. This has to be done with a specific time delay.
It's like,
Check status variable value
Display some text
Wait for 10 seconds
Check status variable value
Display some text
Wait for 15 seconds
and so on. The time delay may vary and it is set once the text is displayed.
I have tried Thread.sleep(time delay) and it failed. Any better way to get this done?
You should use Handler's postDelayed function for this purpose. It will run your code with specified delay on the main UI thread, so you will be able to update UI controls.
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
#Override
protected void onCreate(Bundle bundle) {
// your code here
mHandler = new Handler();
startRepeatingTask();
}
#Override
public void onDestroy() {
super.onDestroy();
stopRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
try {
updateStatus(); //this function can change value of mInterval.
} finally {
// 100% guarantee that this always happens, even if
// your update method throws an exception
mHandler.postDelayed(mStatusChecker, mInterval);
}
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
To anyone interested, here's a class I created using inazaruk's code that creates everything needed (I called it UIUpdater because I use it to periodically update the UI, but you can call it anything you like):
import android.os.Handler;
/**
* A class used to perform periodical updates,
* specified inside a runnable object. An update interval
* may be specified (otherwise, the class will perform the
* update every 2 seconds).
*
* #author Carlos Simões
*/
public class UIUpdater {
// Create a Handler that uses the Main Looper to run in
private Handler mHandler = new Handler(Looper.getMainLooper());
private Runnable mStatusChecker;
private int UPDATE_INTERVAL = 2000;
/**
* Creates an UIUpdater object, that can be used to
* perform UIUpdates on a specified time interval.
*
* #param uiUpdater A runnable containing the update routine.
*/
public UIUpdater(final Runnable uiUpdater) {
mStatusChecker = new Runnable() {
#Override
public void run() {
// Run the passed runnable
uiUpdater.run();
// Re-run it after the update interval
mHandler.postDelayed(this, UPDATE_INTERVAL);
}
};
}
/**
* The same as the default constructor, but specifying the
* intended update interval.
*
* #param uiUpdater A runnable containing the update routine.
* #param interval The interval over which the routine
* should run (milliseconds).
*/
public UIUpdater(Runnable uiUpdater, int interval){
UPDATE_INTERVAL = interval;
this(uiUpdater);
}
/**
* Starts the periodical update routine (mStatusChecker
* adds the callback to the handler).
*/
public synchronized void startUpdates(){
mStatusChecker.run();
}
/**
* Stops the periodical update routine from running,
* by removing the callback.
*/
public synchronized void stopUpdates(){
mHandler.removeCallbacks(mStatusChecker);
}
}
You can then create a UIUpdater object inside your class and use it like so:
...
mUIUpdater = new UIUpdater(new Runnable() {
#Override
public void run() {
// do stuff ...
}
});
// Start updates
mUIUpdater.startUpdates();
// Stop updates
mUIUpdater.stopUpdates();
...
If you want to use this as an activity updater, put the start call inside the onResume() method and the stop call inside the onPause(), so the updates start and stop according to the activity visibility.
I think the new hotness is to use a ScheduledThreadPoolExecutor. Like so:
private final ScheduledThreadPoolExecutor executor_ =
new ScheduledThreadPoolExecutor(1);
this.executor_.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
update();
}
}, 0L, kPeriod, kTimeUnit);
There are 3 ways to do it:
Use ScheduledThreadPoolExecutor
A bit of overkill since you don't need a pool of Thread
//----------------------SCHEDULER-------------------------
private final ScheduledThreadPoolExecutor executor_ =
new ScheduledThreadPoolExecutor(1);
ScheduledFuture<?> schedulerFuture;
public void startScheduler() {
schedulerFuture= executor_.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
//DO YOUR THINGS
pageIndexSwitcher.setVisibility(View.GONE);
}
}, 0L, 5*MILLI_SEC, TimeUnit.MILLISECONDS);
}
public void stopScheduler() {
pageIndexSwitcher.setVisibility(View.VISIBLE);
schedulerFuture.cancel(false);
startScheduler();
}
Use Timer Task
Old Android Style
//----------------------TIMER TASK-------------------------
private Timer carousalTimer;
private void startTimer() {
carousalTimer = new Timer(); // At this line a new Thread will be created
carousalTimer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//DO YOUR THINGS
pageIndexSwitcher.setVisibility(INVISIBLE);
}
}, 0, 5 * MILLI_SEC); // delay
}
void stopTimer() {
carousalTimer.cancel();
}
Use Handler and Runnable
Modern Android Style
//----------------------HANDLER-------------------------
private Handler taskHandler = new android.os.Handler();
private Runnable repeatativeTaskRunnable = new Runnable() {
public void run() {
//DO YOUR THINGS
}
};
void startHandler() {
taskHandler.postDelayed(repeatativeTaskRunnable, 5 * MILLI_SEC);
}
void stopHandler() {
taskHandler.removeCallbacks(repeatativeTaskRunnable);
}
Non-Leaky Handler with Activity / Context
Declare an inner Handler class which does not leak Memory in your Activity/Fragment class
/**
* Instances of static inner classes do not hold an implicit
* reference to their outer class.
*/
private static class NonLeakyHandler extends Handler {
private final WeakReference<FlashActivity> mActivity;
public NonLeakyHandler(FlashActivity activity) {
mActivity = new WeakReference<FlashActivity>(activity);
}
#Override
public void handleMessage(Message msg) {
FlashActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
Declare a runnable which will perform your repetitive task in your Activity/Fragment class
private Runnable repeatativeTaskRunnable = new Runnable() {
public void run() {
new Handler(getMainLooper()).post(new Runnable() {
#Override
public void run() {
//DO YOUR THINGS
}
};
Initialize Handler object in your Activity/Fragment (here FlashActivity is my activity class)
//Task Handler
private Handler taskHandler = new NonLeakyHandler(FlashActivity.this);
To repeat a task after fix time interval
taskHandler.postDelayed(repeatativeTaskRunnable , DELAY_MILLIS);
To stop the repetition of task
taskHandler .removeCallbacks(repeatativeTaskRunnable );
UPDATE: In Kotlin:
//update interval for widget
override val UPDATE_INTERVAL = 1000L
//Handler to repeat update
private val updateWidgetHandler = Handler()
//runnable to update widget
private var updateWidgetRunnable: Runnable = Runnable {
run {
//Update UI
updateWidget()
// Re-run it after the update interval
updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
}
}
// SATART updating in foreground
override fun onResume() {
super.onResume()
updateWidgetHandler.postDelayed(updateWidgetRunnable, UPDATE_INTERVAL)
}
// REMOVE callback if app in background
override fun onPause() {
super.onPause()
updateWidgetHandler.removeCallbacks(updateWidgetRunnable);
}
Timer works fine. Here, I use Timer to search text after 1.5s and update UI. Hope that helps.
private Timer _timer = new Timer();
_timer.schedule(new TimerTask() {
#Override
public void run() {
// use runOnUiThread(Runnable action)
runOnUiThread(new Runnable() {
#Override
public void run() {
search();
}
});
}
}, timeInterval);
Using kotlin and its Coroutine its quite easy, first declare a job in your class (better in your viewModel) like this:
private var repeatableJob: Job? = null
then when you want to create and start it do this:
repeatableJob = viewModelScope.launch {
while (isActive) {
delay(5_000)
loadAlbums(iImageAPI, titleHeader, true)
}
}
repeatableJob?.start()
and if you want to finish it:
repeatableJob?.cancel()
PS: viewModelScope is only available in view models, you can use other Coroutine scopes such as withContext(Dispatchers.IO)
More information: Here
Timer is another way to do your work but be quiet sure to add runOnUiThread if you are working with UI.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity {
CheckBox optSingleShot;
Button btnStart, btnCancel;
TextView textCounter;
Timer timer;
MyTimerTask myTimerTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
optSingleShot = (CheckBox)findViewById(R.id.singleshot);
btnStart = (Button)findViewById(R.id.start);
btnCancel = (Button)findViewById(R.id.cancel);
textCounter = (TextView)findViewById(R.id.counter);
btnStart.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
if(timer != null){
timer.cancel();
}
//re-schedule timer here
//otherwise, IllegalStateException of
//"TimerTask is scheduled already"
//will be thrown
timer = new Timer();
myTimerTask = new MyTimerTask();
if(optSingleShot.isChecked()){
//singleshot delay 1000 ms
timer.schedule(myTimerTask, 1000);
}else{
//delay 1000ms, repeat in 5000ms
timer.schedule(myTimerTask, 1000, 5000);
}
}});
btnCancel.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
if (timer!=null){
timer.cancel();
timer = null;
}
}
});
}
class MyTimerTask extends TimerTask {
#Override
public void run() {
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
runOnUiThread(new Runnable(){
#Override
public void run() {
textCounter.setText(strDate);
}});
}
}
}
and xml is...
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context=".MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:autoLink="web"
android:text="http://android-er.blogspot.com/"
android:textStyle="bold" />
<CheckBox
android:id="#+id/singleshot"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Single Shot"/>
Another Way to use CountDownTimer
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
}
public void onFinish() {
mTextField.setText("done!");
}
}.start();
Schedule a countdown until a time in the future, with regular notifications on intervals along the way. Example of showing a 30 second countdown in a text field:
For Details
Try following example it works !!!
Use [Handler] in onCreate() method which makes use of postDelayed() method that Causes the Runnable to be added to the message queue, to be run after the specified amount of time elapses that is 0 in given example. 1
Refer this code :
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//------------------
//------------------
android.os.Handler customHandler = new android.os.Handler();
customHandler.postDelayed(updateTimerThread, 0);
}
private Runnable updateTimerThread = new Runnable()
{
public void run()
{
//write here whaterver you want to repeat
customHandler.postDelayed(this, 1000);
}
};
You can use a Handler to post runnable code. This technique is outlined very nicely here: https://guides.codepath.com/android/Repeating-Periodic-Tasks
Based on the above post concerning the ScheduledThreadPoolExecutor, I came up with a utility that suited my needs (wanted to fire a method every 3 seconds):
class MyActivity {
private ScheduledThreadPoolExecutor mDialogDaemon;
private void initDebugButtons() {
Button btnSpawnDialogs = (Button)findViewById(R.id.btn_spawn_dialogs);
btnSpawnDialogs.setVisibility(View.VISIBLE);
btnSpawnDialogs.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
spawnDialogs();
}
});
}
private void spawnDialogs() {
if (mDialogDaemon != null) {
mDialogDaemon.shutdown();
mDialogDaemon = null;
}
mDialogDaemon = new ScheduledThreadPoolExecutor(1);
// This process will execute immediately, then execute every 3 seconds.
mDialogDaemon.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do something worthwhile
}
});
}
}, 0L, 3000L, TimeUnit.MILLISECONDS);
}
}
In my case, I had to execute a process if one of these conditions were true: if a previous process was completed or if 5 seconds had already passed. So, I did the following and worked pretty well:
private Runnable mStatusChecker;
private Handler mHandler;
class {
method() {
mStatusChecker = new Runnable() {
int times = 0;
#Override
public void run() {
if (times < 5) {
if (process1.isRead()) {
executeProcess2();
} else {
times++;
mHandler.postDelayed(mStatusChecker, 1000);
}
} else {
executeProcess2();
}
}
};
mHandler = new Handler();
startRepeatingTask();
}
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
}
If process1 is read, it executes process2. If not, it increments the variable times, and make the Handler be executed after one second. It maintains a loop until process1 is read or times is 5. When times is 5, it means that 5 seconds passed and in each second, the if clause of process1.isRead() is executed.
For people using Kotlin, inazaruk's answer will not work, the IDE will require the variable to be initialized, so instead of using the postDelayed inside the Runnable, we'll use it in an separate method.
Initialize your Runnable like this :
private var myRunnable = Runnable {
//Do some work
//Magic happens here ↓
runDelayedHandler(1000) }
Initialize your runDelayedHandler method like this :
private fun runDelayedHandler(timeToWait : Long) {
if (!keepRunning) {
//Stop your handler
handler.removeCallbacksAndMessages(null)
//Do something here, this acts like onHandlerStop
}
else {
//Keep it running
handler.postDelayed(myRunnable, timeToWait)
}
}
As you can see, this approach will make you able to control the lifetime of the task, keeping track of keepRunning and changing it during the lifetime of the application will do the job for you.
I have created a sample/demo/test program in Android that runs quite nicely, if you see below you will see I have created a thread. Now I want to create another thread to work with another handler... since I cannot have two run() methods... how do I do this?
This is my (working - no errors) program:
package com.ryan1;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.TextView;
public class main extends Activity implements Runnable{
int level = 0;
int seconds_running=0;
TextView the_seconds,the_level;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
the_seconds = (TextView) findViewById(R.id.textview_seconds);
the_level = (TextView) findViewById(R.id.textview_level);
Thread thread = new Thread(this);
Thread thread2 = new Thread(this);
thread.start();
thread2.start();
}
public void run() {
while(seconds_running<500)
{
if(seconds_running %5 ==0){level++;}
try {
handler.sendEmptyMessage(0);
int a = 1000 - (level*100);
if(a<=100){a=25;}
Thread.sleep(a);
System.out.println("R "+Thread.currentThread());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
seconds_running++;
int a = 1000 - (level*100);
the_seconds.setText(" "+seconds_running);
the_level.setText(level+" "+a);
}
};
}
Use anonymous class like this.
Thread thread2 = new Thread( new Runnable() {
public void run() {
// code here with your new handler
}
});
make two inner classes that extends Thread.
create an object for both the classes and call start on those objects.
You are suggesting that you want two runnables, yet you only have one runnable defined, which is your 'main' class. So what you need to do is make two different runnables, so that each can have their own code that can be run.
I would make two new classes, lets say, Runnable1 and Runnable2. I would have both of them implement the runnable interface. Each one of them can then contain different code to run in a separate thread.
Finally, I would change your thread creation/start code to look like this:
Thread thread = new Thread(new Runnable1());
Thread thread2 = new Thread(new Runnable2());
thread.start();
thread2.start();
I have an extended dialog class that I want to show for 3 seconds then disappear. This works great the first 2 times it's called, but then it crashes my app after that. Admittedly, I'm not the best with threads and I think that's where my problem might be. As you can see from the code below (commented out section), I tried using a cancel event to kill the thread that is spawned, but that makes it crash the first time it's run. I've also tried doing all of this on the parent class' UI thread which yields the same result as this (crashes after 3 times displaying the dialog).
import java.util.Timer;
import java.util.TimerTask;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
public class HandResults extends Dialog implements DialogInterface {
HandResults hr;
Timer myTimer;
Handler hand = new Handler();
Thread t;
public HandResults(Context context) {
super(context);
setContentView(R.layout.handresults);
hr = this;
/*
this.setOnCancelListener(new OnCancelListener(){
public void onCancel(DialogInterface dialog) {
t.destroy();
}
});
*/
}
public void showHands(){
this.show();
myTimer = null;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
TimerMethod();
}
}, 3000);
}
private void TimerMethod()
{
t = new Thread(){
public void run(){
hand.post(Timer_Tick);
}
};
t.start();
}
private Runnable Timer_Tick = new Runnable() {
public void run() {
hr.cancel();
}
};
}
When the onCancel event is received you're calling t.destroy() and destroy is a deprecated method.
You don't need to start another thread if you're creating a timer, which already runs asynchronously.
So this might work better:
public class HandResults extends Dialog implements DialogInterface {
HandResults hr;
Timer myTimer;
Handler hand = new Handler();
public HandResults(Context context) {
super(context);
setContentView(R.layout.handresults);
hr = this;
}
public void showHands(){
this.show();
myTimer = null;
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
hr.cancel(); // call the cancel method directly
}
}, 3000);
}
}
There is no need to create your own thread, so the above code should do approximately what you're trying to do.
You don't need the treat t here, you can run hand.post() inside the TimerTask. And even the TimerTask/Timer is not needed, you can use handler.postDelayed().
I don't know where the behaviour you observe comes from, though.
Also, you should consider that your Dialog is closed early (e.g. when the use rotates the screen). You can call handler.removeCallbacks() in that case.