I want to be able to call the following method after a specified delay.
In objective c there was something like:
[self performSelector:#selector(DoSomething) withObject:nil afterDelay:5];
Is there an equivalent of this method in android with java?
For example I need to be able to call a method after 5 seconds.
public void DoSomething()
{
//do something here
}
Kotlin
Handler(Looper.getMainLooper()).postDelayed({
//Do something after 100ms
}, 100)
Java
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
}
}, 100);
The class to import is android.os.handler.
I couldn't use any of the other answers in my case.
I used the native java Timer instead.
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// this code will be executed after 2 seconds
}
}, 2000);
Note: This answer was given when the question didn't specify Android as the context. For an answer specific to the Android UI thread look here.
It looks like the Mac OS API lets the current thread continue, and schedules the task to run asynchronously. In the Java, the equivalent function is provided by the java.util.concurrent package. I'm not sure what limitations Android might impose.
private static final ScheduledExecutorService worker =
Executors.newSingleThreadScheduledExecutor();
void someMethod() {
⋮
Runnable task = new Runnable() {
public void run() {
/* Do something… */
}
};
worker.schedule(task, 5, TimeUnit.SECONDS);
⋮
}
For executing something in the UI Thread after 5 seconds:
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
//Do something here
}
}, 5000);
Kotlin & Java Many Ways
1. Using Handler
Handler().postDelayed({
TODO("Do something")
}, 2000)
2. Using TimerTask
Timer().schedule(object : TimerTask() {
override fun run() {
TODO("Do something")
}
}, 2000)
Or even shorter
Timer().schedule(timerTask {
TODO("Do something")
}, 2000)
Or shortest would be
Timer().schedule(2000) {
TODO("Do something")
}
3. Using Executors
Executors.newSingleThreadScheduledExecutor().schedule({
TODO("Do something")
}, 2, TimeUnit.SECONDS)
In Java
1. Using Handler
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Do something
}
}, 2000);
2. Using Timer
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// Do something
}
}, 2000);
3. Using ScheduledExecutorService
private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run() {
// Do something
}
};
worker.schedule(runnable, 2, TimeUnit.SECONDS);
you can use Handler inside UIThread:
runOnUiThread(new Runnable() {
#Override
public void run() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//add your code here
}
}, 1000);
}
});
Thanks for all the great answers, I found a solution that best suits my needs.
Handler myHandler = new DoSomething();
Message m = new Message();
m.obj = c;//passing a parameter here
myHandler.sendMessageDelayed(m, 1000);
class DoSomething extends Handler {
#Override
public void handleMessage(Message msg) {
MyObject o = (MyObject) msg.obj;
//do something here
}
}
See this demo:
import java.util.Timer;
import java.util.TimerTask;
class Test {
public static void main( String [] args ) {
int delay = 5000;// in ms
Timer timer = new Timer();
timer.schedule( new TimerTask(){
public void run() {
System.out.println("Wait, what..:");
}
}, delay);
System.out.println("Would it run?");
}
}
More Safety - With Kotlin Coroutine
Most of the answers use Handler but I give a different solution to delay in activity, fragment, view model with Android Lifecycle ext. This way will auto cancel when the lifecycle begins destroyed - avoid leaking the memory or crashed app
In Activity or Fragment:
lifecycleScope.launch {
delay(DELAY_MS)
doSomething()
}
In ViewModel:
viewModelScope.lanch {
delay(DELAY_MS)
doSomething()
}
In suspend function: (Kotlin Coroutine)
suspend fun doSomethingAfter(){
delay(DELAY_MS)
doSomething()
}
If you get an error with the lifecycleScope not found! - import this dependency to the app gradle file:
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"
If you have to use the Handler, but you are into another thread, you can use runonuithread to run the handler in UI thread. This will save you from Exceptions thrown asking to call Looper.Prepare()
runOnUiThread(new Runnable() {
#Override
public void run() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 1 second
}
}, 1000);
}
});
Looks quite messy, but this is one of the way.
I prefer to use View.postDelayed() method, simple code below:
mView.postDelayed(new Runnable() {
#Override
public void run() {
// Do something after 1000 ms
}
}, 1000);
Here is my shortest solution:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
}
}, 100);
If you are using Android Studio 3.0 and above you can use lambda expressions. The method callMyMethod() is called after 2 seconds:
new Handler().postDelayed(() -> callMyMethod(), 2000);
In case you need to cancel the delayed runnable use this:
Handler handler = new Handler();
handler.postDelayed(() -> callMyMethod(), 2000);
// When you need to cancel all your posted runnables just use:
handler.removeCallbacksAndMessages(null);
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
//DO SOME ACTIONS HERE , THIS ACTIONS WILL WILL EXECUTE AFTER 5 SECONDS...
}
});
}
}, 5000);
I suggest the Timer, it allows you to schedule a method to be called on a very specific interval. This will not block your UI, and keep your app resonsive while the method is being executed.
The other option, is the wait(); method, this will block the current thread for the specified length of time. This will cause your UI to stop responding if you do this on the UI thread.
So there are a few things to consider here as there are so many ways to skin this cat. Although answers have all already been given selected and chosen. I think it's important that this gets revisited with proper coding guidelines to avoid anyone going the wrong direction just because of "majority selected simple answer".
So first let's discuss the simple Post Delayed answer that is the winner selected answer overall in this thread.
A couple of things to consider. After the post delay, you can encounter memory leaks, dead objects, life cycles that have gone away, and more. So handling it properly is important as well. You can do this in a couple of ways.
For sake of modern development, I'll supply in KOTLIN
Here is a simple example of using the UI thread on a callback and confirming that your activity is still alive and well when you hit your callback.
Handler(Looper.getMainLooper()).postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
However, this is still not perfect as there is no reason to hit your callback if the activity has gone away. so a better way would be to keep a reference to it and remove it's callbacks like this.
private fun showFacebookStylePlus1NewsFeedOnPushReceived(){
A35Log.v(TAG, "showFacebookStylePlus1NewsFeedOnPushReceived")
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.VISIBLE
mHandler.postDelayed({
if(activity != null && activity?.isFinishing == false){
txtNewInfo.visibility = View.GONE
}
}, NEW_INFO_SHOW_TIMEOUT_MS)
}
}
and of course handle cleanup on the onPause so it doesn't hit the callback.
override fun onPause() {
super.onPause()
mHandler.removeCallbacks(null)
}
Now that we have talked through the obvious, let's talk about a cleaner option with modern day coroutines and kotlin :). If you aren't using these yet, you are really missing out.
fun doActionAfterDelay()
launch(UI) {
delay(MS_TO_DELAY)
actionToTake()
}
}
or if you want to always do a UI launch on that method you can simply do:
fun doActionAfterDelay() = launch(UI){
delay(MS_TO_DELAY)
actionToTake()
}
Of course just like the PostDelayed you have to make sure you handle canceling so you can either do the activity checks after the delay call or you can cancel it in the onPause just like the other route.
var mDelayedJob: Job? = null
fun doActionAfterDelay()
mDelayedJob = launch(UI) {
try {
delay(MS_TO_DELAY)
actionToTake()
}catch(ex: JobCancellationException){
showFancyToast("Delayed Job canceled", true, FancyToast.ERROR, "Delayed Job canceled: ${ex.message}")
}
}
}
}
//handle cleanup
override fun onPause() {
super.onPause()
if(mDelayedJob != null && mDelayedJob!!.isActive) {
A35Log.v(mClassTag, "canceling delayed job")
mDelayedJob?.cancel() //this should throw CancelationException in coroutine, you can catch and handle appropriately
}
}
If you put the launch(UI) into the method signature the job can be assigned in the calling line of code.
so moral of the story is to be safe with your delayed actions, make sure you remove your callbacks, or cancel your jobs and of course confirm you have the right life cycle to touch items on your delay callback complete. The Coroutines also offers cancelable actions.
Also worth noting that you should typically handle the various exceptions that can come with coroutines. For example, a cancelation, an exception, a timeout, whatever you decide to use. Here is a more advanced example if you decide to really start utilizing coroutines.
mLoadJob = launch(UI){
try {
//Applies timeout
withTimeout(4000) {
//Moves to background thread
withContext(DefaultDispatcher) {
mDeviceModelList.addArrayList(SSDBHelper.getAllDevices())
}
}
//Continues after async with context above
showFancyToast("Loading complete", true, FancyToast.SUCCESS)
}catch(ex: JobCancellationException){
showFancyToast("Save canceled", true, FancyToast.ERROR, "Save canceled: ${ex.message}")
}catch (ex: TimeoutCancellationException) {
showFancyToast("Timed out saving, please try again or press back", true, FancyToast.ERROR, "Timed out saving to database: ${ex.message}")
}catch(ex: Exception){
showFancyToast("Error saving to database, please try again or press back", true, FancyToast.ERROR, "Error saving to database: ${ex.message}")
}
}
For a Simple line Handle Post delay, you can do as following :
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// Do someting
}
}, 3000);
I hope this helps
You can use this for Simplest Solution:
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Write your code here
}
}, 5000); //Timer is in ms here.
Else, Below can be another clean useful solution:
new Handler().postDelayed(() ->
{/*Do something here*/},
5000); //time in ms
You can make it much cleaner by using the newly introduced lambda expressions:
new Handler().postDelayed(() -> {/*your code here*/}, time);
Using Kotlin, we can achieve by doing the following
Handler().postDelayed({
// do something after 1000ms
}, 1000)
If you use RxAndroid then thread and error handling becomes much easier. Following code executes after a delay
Observable.timer(delay, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> {
// Execute code here
}, Throwable::printStackTrace);
I created simpler method to call this.
public static void CallWithDelay(long miliseconds, final Activity activity, final String methodName)
{
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
try {
Method method = activity.getClass().getMethod(methodName);
method.invoke(activity);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}, miliseconds);
}
To use it, just call : .CallWithDelay(5000, this, "DoSomething");
Below one works when you get,
java.lang.RuntimeException: Can't create handler inside thread that
has not called Looper.prepare()
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
}
}, 100);
It's very easy using the CountDownTimer.
For more details https://developer.android.com/reference/android/os/CountDownTimer.html
import android.os.CountDownTimer;
// calls onTick every second, finishes after 3 seconds
new CountDownTimer(3000, 1000) {
public void onTick(long millisUntilFinished) {
Log.d("log", millisUntilFinished / 1000);
}
public void onFinish() {
// called after count down is finished
}
}.start();
I like things cleaner:
Here is my implementation, inline code to use inside your method
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
}
}, 100);
everybody seems to forget to clean the Handler before posting a new runnable or message on it. Otherway they could potentially accumulate and cause bad behaviour.
handler.removeMessages(int what);
// Remove any pending posts of messages with code 'what' that are in the message queue.
handler.removeCallbacks(Runnable r)
// Remove any pending posts of Runnable r that are in the message queue.
Here is another tricky way: it won't throw exception when the runnable change UI elements.
public class SimpleDelayAnimation extends Animation implements Animation.AnimationListener {
Runnable callBack;
public SimpleDelayAnimation(Runnable runnable, int delayTimeMilli) {
setDuration(delayTimeMilli);
callBack = runnable;
setAnimationListener(this);
}
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
callBack.run();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
}
You can call the animation like this:
view.startAnimation(new SimpleDelayAnimation(delayRunnable, 500));
Animation can attach to any view.
Here is the answer in Kotlin you lazy, lazy people:
Handler().postDelayed({
//doSomethingHere()
}, 1000)
Kotlin
runOnUiThread from a Fragment
Timer
example:
Timer().schedule(500) {
activity?.runOnUiThread {
// code
}
}
A suitable solution in android:
private static long SLEEP_TIME = 2 // for 2 second
.
.
MyLauncher launcher = new MyLauncher();
launcher.start();
.
.
private class MyLauncher extends Thread {
#Override
/**
* Sleep for 2 seconds as you can also change SLEEP_TIME 2 to any.
*/
public void run() {
try {
// Sleeping
Thread.sleep(SLEEP_TIME * 1000);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
//do something you want to do
//And your code will be executed after 2 second
}
}
I need to delete a value from SharedPreferences after 5 minutes or when the user finished to do something . So when I add that value I start this:
Activity A
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
}, Utils.TIME_BEFORE_DELETE);
and in the case users finished all I do this:
Activity B
mySharedPrefernces.removeValue(mContext, Utils.MY_VALUE);
But how can I stop the Handle into second activity?? Or is there another way to do it??
you can you boolean variable if you want to cancel this.
create public static boolean to check if the task is cancelled or not.
public static boolean isCanceled = false;
Use this in run() method
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (!isCanceled)
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
}, Utils.TIME_BEFORE_DELETE);
if you want to cancel then set:
isCanceled = true;
Runnable run = new Runnable() {
#Override
public void run() {
mySharedPreferences.removeValue(mContext, Utils.MY_VALUE);
}
};
Handler handler = new Handler();
handler.postDelayed(run, Utils.TIME_BEFORE_DELETE);
//to dismiss pending runnable
handler.removeCallbacks(run);
A better way to do: Example code
publc static final Handler handler = new Handler();
public static final Runnable runnable = new Runnable() {
public void run() {
try {
Log.d("Runnable","Handler is working");
if(i == 5){ // just remove call backs
handler.removeCallbacks(this);
Log.d("Runnable","ok");
} else { // post again
i++;
handler.postDelayed(this, 5000);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
//now somewhere in a method
b1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
handler.removeCallbacks(runnable);
handler.postDelayed(runnable, 5000);
}
});
You can use handler.removeCallbacksAndMessages(null);. More information link
In this case you can use service with sticky flags. So you start service with intent "start_handler" and start handler also. When you need cancel handler you send the intent to stop handler and service. Or when time is passed and handler calls your code you should also stop service.
Using service with sticky flag provides possibility restoring handler. Also you need add some logic saving time when handler was run for correct restoring handler.
For that you can't use direct Runnable inside handler, you need to take one instance of it then you can do this like below,
Runnable myRunnable = new Runnable(){};
Then assign this in handler
handler.postDelayed(myRunnable);
And on no need use below line
handler.removeCallbacks(myRunnable);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
//add your code hare
finish();
}
}, 10000);
by using this way you can stop your runnable in a fix time
I'm trying to animate 4 images in succession, switching the animation when I get a new GCM message that sends a Broadcast Intent. I'll show the code for the first 2, and what is going wrong. Basically between the two commands(case 0 vs case 1), I need to be able to stop the first runnable and then start the 2nd. I try to do that by setting
isRunning = false;
but that doesn't work. I'm thinking if I kept hacking away I may get this right, but I am wondering what the correct way to do it is.
public void startAnimatedBackground(Integer num) {
isRunning = false;
ImageSwitcher imageSwitcher = null;
aniIn = AnimationUtils.loadAnimation(this,
android.R.anim.fade_in);
aniOut = AnimationUtils.loadAnimation(this,
android.R.anim.fade_out);
aniIn.setDuration(500);
aniOut.setDuration(500);
switch (num) {
case 0:
imageSwitcher = (ImageSwitcher) findViewById(R.id.switcher_accept);
break;
case 1:
imageSwitcher = (ImageSwitcher) findViewById(R.id.switcher_on_way);
break;
default:
break;
}
imageSwitcher.setInAnimation(aniIn);
imageSwitcher.setOutAnimation(aniOut);
imageSwitcher.setFactory(this);
imageSwitcher.setImageResource(images[0]);
isRunning = true;
final Handler handler = new Handler();
final ImageSwitcher finalImageSwitcher = imageSwitcher;
Runnable runnable = new Runnable() {
#Override
public void run() {
if (isRunning) {
System.out.println("Running.."+finalImageSwitcher+index);
index++;
index = index % images.length;
finalImageSwitcher.setImageResource(images[index]);
handler.postDelayed(this, interval);
}
}
};
handler.postDelayed(runnable, interval);
}
This is what happens at first, and it is correct. I get a blinking image.
...app:id/switcher_accept}1
...app:id/switcher_accept}0
...app:id/switcher_accept}1
...app:id/switcher_accept}0
...app:id/switcher_accept}1
After case 2 runs, this is what the running process looks like. As you can see, both are running, and none of the expected behavior is happening. What I want is the 2nd(switcher_on_way) to run just like the first was before. I was hoping my isRunning=false; code would let this happen, but it obviously isn't.
...app:id/switcher_on_way}0
...app:id/switcher_accept}1
...app:id/switcher_on_way}0
...app:id/switcher_accept}1
...app:id/switcher_on_way}0
...app:id/switcher_accept}1
Your problem lies in this block:
Runnable runnable = new Runnable() {
#Override
public void run() {
if (isRunning) {
System.out.println("Running.."+finalImageSwitcher+index);
...
handler.postDelayed(this, interval);
}
}
};
handler.postDelayed(runnable, interval);
You tried to create a loop and control it via isRunning variable. However, the problem is the condition is checked in the middle of the interval when isRunning is true.
1: Start _isRunning=false______Check(isRunning)________Check(isRunning)
2: ___Start _isRunning=false___isRunning=true_______isRunning=true
and you need other approach, for example: create global handler instead of local and then cancel the postDelayed when you start a new animation.
Refer to: cancelling a handler.postdelayed process
or you can use wait, synchronized, and notify.
Now the image is changed as soon as I click on.
I would like to make this process AUTOMATIC (ex. every second)
this is my actually code
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageView:
foto.setVisibility(View.INVISIBLE);
foto1.setVisibility(View.VISIBLE);
break;
case R.id.imageView2:
foto1.setVisibility(View.INVISIBLE);
foto.setVisibility(View.VISIBLE);
}
}
Have a look at ViewFlipper
http://developer.android.com/reference/android/widget/ViewFlipper.html
You can set the delay using setFlipInterval(int) or in the XML using android:flipInterval
Yo can have a periodic task to do it:
ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(1);
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
if (foto.getVisibility == View.VISIBLE) {
foto.setVisibility(View.INVISIBLE);
foto1.setVisibility(View.VISIBLE);
} else {
foto.setVisibility(View.VISIBLE);
foto1.setVisibility(View.INVISIBLE);
}
}
});
}
}, 0, 1, TimeUnit.SECONDS);
You should use a Handler with `postDelayed'. See this answer for some code.
Also, you can try using 'ImageSwitcher' instead of two 'ImageView's
Try this:
boolean isFirstVisible;
long millis;
while(true) {
millis = System.currentTimeMillis();
if (isFirstVisible) {
foto1.setVisibility(View.INVISIBLE);
foto.setVisibility(View.VISIBLE);
isFirstVisible = false;
} else {
foto.setVisibility(View.INVISIBLE);
foto1.setVisibility(View.VISIBLE);
isFirstVisible = true;
}
Thread.sleep(1000 - millis % 1000);
}
maybe use ViewSwitcher (in your casae ImageSwitcher should work) and switch Views using Handler?
private static final int delay=1000; //ms
Handler h = new Handler();
Runnable r = new Runnable(){
public run(){
//viewSwitcher.showNext();
//exampole of swtiching
h.postDelayed(r, delay);
}
}
h.postDelayed(r, delay);
to stop this loop use h.removeCallbacks(r)
you may also use viewSwitcher.postDelayed
Can someone explain to me 2 things about the thread code that I finally made almost working the way it should. I want to do a periodic task in the background every x seconds and be able to stop and start it at will. I coded that based on the examples I found, but I'm not sure if I made it in the right way. For the purpose of debugging, the task is displaying a time with custom showTime().
public class LoopExampleActivity extends Activity {
TextView Napis, Napis2;
Button button1,button_start,button_stop;
Handler handler = new Handler();
Boolean tread1_running = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Napis = (TextView) findViewById(R.id.textView1);
Napis2 = (TextView) findViewById(R.id.textView2);
button1 = (Button) findViewById(R.id.button1);
button_stop = (Button) findViewById(R.id.button_stop);
button_start = (Button) findViewById(R.id.button_start);
button_stop.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
tread1_running = false;
}
});
button_start.setOnClickListener(new OnClickListener() {
#Override
public void onClick (View v) {
tread1_running = true;
}
});
thread.start();
}// endof onCreate
final Runnable r = new Runnable()
{
public void run()
{
handler.postDelayed(this, 1000);
showTime(Napis2);
}
};
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(tread1_running) {
sleep(1000);
handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}
Now the questions are:
1)Will my thread quit forever if I stop it with the stop button?
2)Why can't I start it again with the start_button? If I add the tread.start() in a button, will it crash?
3) I tried a second version when I let the thread run and put a condition into the handler. The only way I can get it to work is to loop conditionaly in the handler by adding an
if (thread1_running) {
handler.postDelayed(this, 2000);
showTime(Napis2);
}
And changing the condition in a thread start to while (true) but then I have an open thread that is running all the time and I start and stop it in a handler, and it posts more and more handlers.
So, finally I get to the point it looks like that:
final Runnable r = new Runnable()
{
public void run()
{
if (thread1_running) handler.postDelayed(this, 1000);
showTime(Napis2);
}
};
Thread thread = new Thread()
{
#Override
public void run() {
try {
while(true) {
sleep(1000);
if (thread1_running) handler.post(r);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Is the proper way to do that is to start and stop a whole thread? Or that is the best way?
The best way to achieve something like that would be, in my humble opinion, to postDelayed(Runnable, long).
You could do something like this. Class definition:
private Handler mMessageHandler = new Handler();
private Runnable mUpdaterRunnable = new Runnable() {
public void run() {
doStuff();
showTime(Napis2);
mMessageHandler.postDelayed(mUpdaterRunnable, 1000);
}
};
And control true run/stop like this:
To start:
mMessageHandler.postDelayed(mUpdaterRunnable, 1000);
And to stop:
mMessageHandler.removeCallbacks(mUpdaterRunnable);
It's much much simpler, in my humble opinion.
Threads a described by a state machine in java.
When a thread get outs of its run method, it enters in the stopped state and can't be restarted.
You should always stop a thread by getting it out of its run method as you do, it s the proper way to do it.
If you want to "restart the thread", start a new instance of your thread class.
You should better encapsulate your thread and its running field. It should be inside your thread class and the class should offer a public method to swich the boolean. No one cares about your datastructure, hide them. :)
You should consider using runOnUIThread for your runnable, its much easier to use than handlers.